From ff0238385fac58f7b889645aded42b354d1c47ca Mon Sep 17 00:00:00 2001 From: Tetsuharu OHZEKI Date: Tue, 22 Mar 2016 15:52:07 +0900 Subject: [PATCH 1/2] chore(TypeScript): Enable 'strictNullChecks' option --- tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tsconfig.json b/tsconfig.json index b7e9ae0e..c38b2a5f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,6 +15,7 @@ "preserveConstEnums": true, "removeComments": false, "sourceMap": true, + "strictNullChecks": true, "suppressImplicitAnyIndexErrors": false, "target": "ES2015" }, From 9660b36e465b47370b0e7031e8a9738d31e8a483 Mon Sep 17 00:00:00 2001 From: Tetsuharu OHZEKI Date: Wed, 27 Apr 2016 02:00:42 +0900 Subject: [PATCH 2/2] fix(typescript): fix compile error --- .../rize/adapter/NotificationService.ts | 6 ++--- src/client/rize/rize.ts | 2 +- src/client/script/adapter/AudioDriver.ts | 6 ++++- src/client/script/domain/Channel.ts | 11 +++----- src/client/script/domain/ChannelDomain.ts | 1 - src/client/script/domain/DomainState.ts | 18 ++++++------- src/client/script/domain/NetworkDomain.ts | 8 ------ .../intent/action/ConnectionActionCreator.ts | 2 +- .../script/output/NotificationPresenter.ts | 5 +--- src/client/script/output/WindowPresenter.ts | 22 ++++++++------- .../output/context/ConnectSettingContext.ts | 10 +++---- .../script/output/context/SidebarContext.ts | 7 ++--- src/client/script/output/view/AppView.ts | 6 ++--- .../script/output/view/GeneralSettingView.ts | 2 +- src/client/script/output/view/InputBoxView.ts | 12 ++++----- .../script/output/view/MessageContentView.ts | 2 -- .../script/output/view/SidebarFooterView.ts | 27 +++++++------------ .../output/viewmodel/ConnectionStore.ts | 4 --- .../script/output/viewmodel/SidebarStore.ts | 10 +------ 19 files changed, 62 insertions(+), 99 deletions(-) diff --git a/src/client/rize/adapter/NotificationService.ts b/src/client/rize/adapter/NotificationService.ts index 2a786013..7777a0aa 100644 --- a/src/client/rize/adapter/NotificationService.ts +++ b/src/client/rize/adapter/NotificationService.ts @@ -80,15 +80,15 @@ function requestPermittion(): Rx.Observable { } function showNotification(topic: NotifedTopic): Rx.Observable { - let notification: Notification = new (window as any).Notification(topic.title, { + let notification: Notification | void = new (window as any).Notification(topic.title, { body: topic.body, icon: topic.icon, }); const timeout = Rx.Observable.empty().delay(5 * 1000); - const click = Rx.Observable.fromEvent(notification, 'click').take(1); + const click = Rx.Observable.fromEvent(notification!, 'click').take(1); const close: Rx.Observable = click.race(timeout).do(function(){ notification.close(); - notification = null; + notification = undefined; }); return close.share(); } \ No newline at end of file diff --git a/src/client/rize/rize.ts b/src/client/rize/rize.ts index 5cd6bc55..aee4f23a 100644 --- a/src/client/rize/rize.ts +++ b/src/client/rize/rize.ts @@ -50,7 +50,7 @@ export class RizeClient { console.log(data.value); }); - const view = React.createElement(RizeAppView, null); + const view = React.createElement(RizeAppView, undefined); const mountpoint = document.getElementById('js-mountpoint-app'); ReactDOM.render(view, mountpoint); } diff --git a/src/client/script/adapter/AudioDriver.ts b/src/client/script/adapter/AudioDriver.ts index be3cf0b4..873634e4 100644 --- a/src/client/script/adapter/AudioDriver.ts +++ b/src/client/script/adapter/AudioDriver.ts @@ -24,7 +24,7 @@ */ export class AudioDriver { - _audio: HTMLAudioElement; + private _audio: HTMLAudioElement | void; constructor(path: string) { const audio = new Audio(); @@ -34,6 +34,10 @@ export class AudioDriver { this._audio = audio; } + destroy(): void { + this._audio = undefined; + } + play(): void { this._audio.play(); } diff --git a/src/client/script/domain/Channel.ts b/src/client/script/domain/Channel.ts index 59876c95..2e87ecfc 100644 --- a/src/client/script/domain/Channel.ts +++ b/src/client/script/domain/Channel.ts @@ -36,9 +36,9 @@ export class Channel { private _userList: Array; private _unread: number; private _messageBuffer: Array; - private _network: Network; + private _network: Network | void; - constructor(raw: any, network: Network = null) { + constructor(raw: any, network: Network | void = undefined) { this.id = raw.id; this.name = raw.name; @@ -55,13 +55,10 @@ export class Channel { this._unread = raw.unread; - let messages: Array = null; + let messages: Array = []; if (Array.isArray(raw.messages)) { messages = raw.messages; } - else { - messages = []; - } this._messageBuffer = messages; this._network = network; @@ -79,7 +76,7 @@ export class Channel { return this._userList; } - getNetwork(): Network { + getNetwork(): Network | void { return this._network; } diff --git a/src/client/script/domain/ChannelDomain.ts b/src/client/script/domain/ChannelDomain.ts index 31b45806..60dd3552 100644 --- a/src/client/script/domain/ChannelDomain.ts +++ b/src/client/script/domain/ChannelDomain.ts @@ -123,7 +123,6 @@ export class ChannelDomain { dispose(): void { this._ignitionDisposable.unsubscribe(); - this._notableDispatcher = null; } getId(): ChannelId { diff --git a/src/client/script/domain/DomainState.ts b/src/client/script/domain/DomainState.ts index 84053c3d..6e8bd684 100644 --- a/src/client/script/domain/DomainState.ts +++ b/src/client/script/domain/DomainState.ts @@ -64,13 +64,13 @@ export class SelectedTab { export class DomainState { private _networkSet: NetworkSetDomain; - private _latestCurrentTab: SelectedTab; + private _latestCurrentTab: SelectedTab | void; private _currentTab: Rx.Observable; private _notifiableMessage: Rx.Observable; constructor(gateway: MessageGateway) { this._networkSet = new NetworkSetDomain(gateway); - this._latestCurrentTab = null; + this._latestCurrentTab = undefined; // In most of case, a rendering operation is depend on the source of `selectTab()`. // So this observable should be on the next event loop. @@ -79,18 +79,18 @@ export class DomainState { }).observeOn(Rx.Scheduler.asap).share(); this._notifiableMessage = this._networkSet.recievedNotifiableMessage() - .withLatestFrom(this._currentTab, function (data, current): RecievedMessage { + .withLatestFrom(this._currentTab, function (data, current): RecievedMessage | void { const isSameChannel: boolean = current.channelId.mapOr(false, function (current: ChannelId) { return data.channelId === current; }); if (isSameChannel) { - return null; + return undefined; } return data; }).filter(function (data) { - return data !== null; - }).share(); + return data !== undefined; + }).map((data) => data!).share(); } /** @@ -100,7 +100,7 @@ export class DomainState { return this._networkSet.legacy; } - get currentTab(): SelectedTab { + get currentTab(): SelectedTab | void { return this._latestCurrentTab; } @@ -155,7 +155,7 @@ function selectTab(gateway: MessageGateway, intent: UIActionDispatcher, set: Net }); const removedNetwork = set.removedNetwork().withLatestFrom(set.getNetworkList(), function(_, list) { - let tab: SelectedTab = null; + let tab: SelectedTab; if (list.length === 0) { tab = new SelectedTab(CurrentTabType.SETTING, 'connect'); } @@ -183,7 +183,7 @@ function selectTab(gateway: MessageGateway, intent: UIActionDispatcher, set: Net }); const initial = set.initialState().map(function(data){ - let tab: SelectedTab = null; + let tab: SelectedTab; const idIsSetting = data.active.mapOr(true, function(id){ return (typeof id !== 'number'); diff --git a/src/client/script/domain/NetworkDomain.ts b/src/client/script/domain/NetworkDomain.ts index 7356e12b..9e17c674 100644 --- a/src/client/script/domain/NetworkDomain.ts +++ b/src/client/script/domain/NetworkDomain.ts @@ -126,15 +126,7 @@ export class NetworkDomain { } dispose(): void { - this._data = null; - this._nickname = null; - this._joinedChannel = null; - this._partedChannel = null; - - this._notableMsgDispatcher = null; - this._subscribed.unsubscribe(); - this._subscribed = null; } getId(): number { diff --git a/src/client/script/intent/action/ConnectionActionCreator.ts b/src/client/script/intent/action/ConnectionActionCreator.ts index bdf8fd63..c7a97259 100644 --- a/src/client/script/intent/action/ConnectionActionCreator.ts +++ b/src/client/script/intent/action/ConnectionActionCreator.ts @@ -35,7 +35,7 @@ export class ConnectionActionCreator { } dispose(): void { - this._dispatcher = null; + (this as any)._dispatcher = undefined; } dispatcher(): ConnectionActionDispatcher { diff --git a/src/client/script/output/NotificationPresenter.ts b/src/client/script/output/NotificationPresenter.ts index cea3c0c3..d306bab8 100644 --- a/src/client/script/output/NotificationPresenter.ts +++ b/src/client/script/output/NotificationPresenter.ts @@ -68,10 +68,7 @@ export class NotificationPresenter { this._disposeRequestPermission.unsubscribe(); this._disposeshowNotification.unsubscribe(); - this._audio = null; - this._disposePlay = null; - this._disposeRequestPermission = null; - this._disposeshowNotification = null; + this._audio.destroy(); } playSound(): void { diff --git a/src/client/script/output/WindowPresenter.ts b/src/client/script/output/WindowPresenter.ts index 6ae1b88b..dbf7af18 100644 --- a/src/client/script/output/WindowPresenter.ts +++ b/src/client/script/output/WindowPresenter.ts @@ -41,14 +41,14 @@ export class WindowPresenter implements EventListenerObject { private _domain: DomainState; private _disposer: Rx.Subscription; - private _currenTab: SelectedTab; + private _currenTab: SelectedTab | void; constructor(domain: DomainState) { this._domain = domain; this._disposer = new Rx.Subscription(); this._disposer.add(AppActionCreator.dispatcher().reload.subscribe(function () { - window.onbeforeunload = null; + (window as any).onbeforeunload = null; location.reload(); })); @@ -63,7 +63,7 @@ export class WindowPresenter implements EventListenerObject { } })); - this._currenTab = null; + this._currenTab = undefined; this._disposer.add(domain.getCurrentTab().subscribe((tab) => { this._currenTab = tab; })); @@ -115,10 +115,6 @@ export class WindowPresenter implements EventListenerObject { window.document.documentElement.removeEventListener('keydown', this); this._disposer.unsubscribe(); - - this._currenTab = null; - this._disposer = null; - this._domain = null; } private _onBeforeUnload(aEvent: Event): string { @@ -166,10 +162,16 @@ export class WindowPresenter implements EventListenerObject { handleShortcut(key: string): void { const channelList: Array = this._domain.networkSet.getChannelList(); - const currentIndex: Option = this._domain.currentTab.channelId.map(function(currentId: ChannelId) { - return channelList.findIndex(function(channel: Channel){ + const currentIndex: Option = this._domain.currentTab.channelId.map(function(currentId: ChannelId): number { + const result = channelList.findIndex(function(channel: Channel){ return channel.id === currentId; }); + if (result === undefined) { + throw new Error('should not be undefined'); + } + else { + return result; + } }); if (currentIndex.isNone) { @@ -213,4 +215,4 @@ export class WindowPresenter implements EventListenerObject { const title = BASE_TITLE + ' - ' + currentName; window.document.title = title; } -} +} \ No newline at end of file diff --git a/src/client/script/output/context/ConnectSettingContext.ts b/src/client/script/output/context/ConnectSettingContext.ts index 10a6fe66..bcae8860 100644 --- a/src/client/script/output/context/ConnectSettingContext.ts +++ b/src/client/script/output/context/ConnectSettingContext.ts @@ -40,7 +40,7 @@ export class ConnectSettingContext implements ViewContext { private _action: ConnectionActionCreator; private _store: ConnectionStore; - private _viewDisposer: Rx.Subscription; + private _viewDisposer: Rx.Subscription | undefined; constructor(gateway: MessageGateway) { if (!gateway) { @@ -49,17 +49,13 @@ export class ConnectSettingContext implements ViewContext { this._action = new ConnectionActionCreator(); this._store = new ConnectionStore(this._action.dispatcher(), gateway); - this._viewDisposer = null; + this._viewDisposer = undefined; } private _destroy(): void { - this._viewDisposer.unsubscribe(); + this._viewDisposer!.unsubscribe(); this._store.dispose(); this._action.dispose(); - - this._viewDisposer = null; - this._store = null; - this._action = null; } onActivate(mountpoint: Element): void { diff --git a/src/client/script/output/context/SidebarContext.ts b/src/client/script/output/context/SidebarContext.ts index 252115c5..b8e8bad6 100644 --- a/src/client/script/output/context/SidebarContext.ts +++ b/src/client/script/output/context/SidebarContext.ts @@ -36,19 +36,16 @@ import {ViewContext} from './ViewContext'; export class SidebarContext implements ViewContext { private _viewmodel: SidebarStore; - private _viewDisposer: Rx.Subscription; + private _viewDisposer: Rx.Subscription | void; constructor(domain: DomainState) { this._viewmodel = new SidebarStore(domain); - this._viewDisposer = null; + this._viewDisposer = undefined; } private _destroy(): void { this._viewDisposer.unsubscribe(); this._viewmodel.dispose(); - - this._viewDisposer = null; - this._viewmodel = null; } onActivate(mountpoint: Element): void { diff --git a/src/client/script/output/view/AppView.ts b/src/client/script/output/view/AppView.ts index 62f188c6..9c4846ec 100644 --- a/src/client/script/output/view/AppView.ts +++ b/src/client/script/output/view/AppView.ts @@ -47,7 +47,7 @@ class AppViewModel { export class AppView { - private _element: Element; + private _element: Element | void; private _vm: AppViewModel; private _disposer: Rx.Subscription; @@ -67,7 +67,7 @@ export class AppView { } destroy(): void { - this._element = null; + this._element = undefined; this._vm.destroy(); this._disposer.unsubscribe(); } @@ -102,7 +102,7 @@ export class AppView { } private _handleClickEvent(): Rx.Subscription { - return Rx.Observable.fromEvent(this._element, 'click', (event: UIEvent) => event.target as Element) + return Rx.Observable.fromEvent(this._element!, 'click', (event: UIEvent) => event.target as Element) .filter((target: Element): boolean => (target.localName === 'button')) .subscribe((target: Element) => { if (target.classList.contains('lt')) { diff --git a/src/client/script/output/view/GeneralSettingView.ts b/src/client/script/output/view/GeneralSettingView.ts index 1c928c26..c78b1d05 100644 --- a/src/client/script/output/view/GeneralSettingView.ts +++ b/src/client/script/output/view/GeneralSettingView.ts @@ -69,7 +69,7 @@ export class GeneralSettingView implements EventListenerObject { const name = target.getAttribute('name'); const value = (target as HTMLInputElement).checked; - SettingActionCreator.setOption(name, value); + SettingActionCreator.setOption(name!, value); if (value && target.getAttribute('id') === 'badge') { NotificationActionCreator.requestPermission(); diff --git a/src/client/script/output/view/InputBoxView.ts b/src/client/script/output/view/InputBoxView.ts index c3d9a399..8dcf2ac0 100644 --- a/src/client/script/output/view/InputBoxView.ts +++ b/src/client/script/output/view/InputBoxView.ts @@ -61,7 +61,7 @@ export class InputBoxView { private _disposer: Rx.Subscription; private _inputVal: InputValue; - private _lastSuggestionCache: Array; + private _lastSuggestionCache: Array | undefined; private _isSuggestion: boolean; constructor(domain: DomainState, element: Element) { @@ -99,7 +99,7 @@ export class InputBoxView { })); this._inputVal = new InputValue('', new None()); - this._lastSuggestionCache = null; + this._lastSuggestionCache = undefined; this._isSuggestion = false; this._init(); @@ -201,16 +201,16 @@ export class InputBoxView { } else { const newly = this._inputVal.suggstedIndex.unwrap() + 1; - index = (newly > (this._lastSuggestionCache.length - 1)) ? 0 : newly; + index = (newly > (this._lastSuggestionCache!.length - 1)) ? 0 : newly; } - if (this._lastSuggestionCache.length === 0) { + if (this._lastSuggestionCache!.length === 0) { return; } this._inputVal = new InputValue(this._inputVal.actual, new Some(index)); this._isSuggestion = true; - this._textInput.value = this._lastSuggestionCache[index]; + this._textInput.value = this._lastSuggestionCache![index]; this._isSuggestion = false; } @@ -230,7 +230,7 @@ export class InputBoxView { const current = this._textInput.value; this._inputVal = new InputValue(current, new None()); - this._lastSuggestionCache = null; + this._lastSuggestionCache = undefined; } private _createSuggestion(value: string): Array { diff --git a/src/client/script/output/view/MessageContentView.ts b/src/client/script/output/view/MessageContentView.ts index 20dd579a..4bee11fe 100644 --- a/src/client/script/output/view/MessageContentView.ts +++ b/src/client/script/output/view/MessageContentView.ts @@ -123,8 +123,6 @@ export class MessageContentView { dispose(): void { this._disposer.unsubscribe(); - this._disposer = null; - this._element = null; } getElement(): Element { diff --git a/src/client/script/output/view/SidebarFooterView.ts b/src/client/script/output/view/SidebarFooterView.ts index 58c38d0c..2deb1acd 100644 --- a/src/client/script/output/view/SidebarFooterView.ts +++ b/src/client/script/output/view/SidebarFooterView.ts @@ -39,7 +39,7 @@ export class SidebarFooterView implements EventListenerObject { _connectElement: HTMLElement; _settingElement: HTMLElement; - _lastSelectedElement: HTMLElement; + _lastSelectedElement: HTMLElement | void; _disposableSignIn: Rx.Subscription; _disposableSignout: Rx.Subscription; @@ -54,30 +54,30 @@ export class SidebarFooterView implements EventListenerObject { this._connectElement = element.querySelector('.connect') as HTMLElement; this._settingElement = element.querySelector('.settings') as HTMLElement; - this._lastSelectedElement = null; + this._lastSelectedElement = undefined; this._disposableSignIn = UIActionCreator.dispatcher().showSignIn.subscribe(() => { - this.selectElement(this._lastSelectedElement, this._signinElement); + this.selectElement(this._lastSelectedElement!, this._signinElement); }); this._disposableSignout = AppActionCreator.dispatcher().signout.subscribe(() => { - this.selectElement(this._lastSelectedElement, this._signoutElement); + this.selectElement(this._lastSelectedElement!, this._signoutElement); }); this._disposableShowConnect = domain.getSelectedSetting().filter(function(id){ return (id === 'connect'); }).subscribe(() => { - this.selectElement(this._lastSelectedElement, this._connectElement); + this.selectElement(this._lastSelectedElement!, this._connectElement); }); this._disposableShowSetting = domain.getSelectedSetting().filter(function(id){ return (id === 'settings'); }).subscribe(() => { - this.selectElement(this._lastSelectedElement, this._settingElement); + this.selectElement(this._lastSelectedElement!, this._settingElement); }); this._disposableSelectChannel = domain.getSelectedChannel().subscribe(() => { - this.selectElement(this._lastSelectedElement, null); + this.selectElement(this._lastSelectedElement!, undefined); }); element.addEventListener('click', this); @@ -91,13 +91,6 @@ export class SidebarFooterView implements EventListenerObject { this._disposableShowConnect.unsubscribe(); this._disposableShowSetting.unsubscribe(); this._disposableSelectChannel.unsubscribe(); - - this._element = null; - this._signinElement = null; - this._signoutElement = null; - this._connectElement = null; - this._settingElement = null; - this._lastSelectedElement = null; } handleEvent(aEvent: Event): void { @@ -128,12 +121,12 @@ export class SidebarFooterView implements EventListenerObject { } } - selectElement(last: HTMLElement, current: HTMLElement): void { - if (last !== null) { + selectElement(last: HTMLElement, current: HTMLElement | void): void { + if (last !== undefined) { this.deactivate(last); } - if (current !== null) { + if (current !== undefined) { this.activate(current); } diff --git a/src/client/script/output/viewmodel/ConnectionStore.ts b/src/client/script/output/viewmodel/ConnectionStore.ts index 835a606d..d76c41a6 100644 --- a/src/client/script/output/viewmodel/ConnectionStore.ts +++ b/src/client/script/output/viewmodel/ConnectionStore.ts @@ -101,9 +101,5 @@ export class ConnectionStore { dispose(): void { this._init.unsubscribe(); this._tryConnect.unsubscribe(); - - this._state = null; - this._init = null; - this._tryConnect = null; } } \ No newline at end of file diff --git a/src/client/script/output/viewmodel/SidebarStore.ts b/src/client/script/output/viewmodel/SidebarStore.ts index 774952d6..e0d5a7db 100644 --- a/src/client/script/output/viewmodel/SidebarStore.ts +++ b/src/client/script/output/viewmodel/SidebarStore.ts @@ -145,14 +145,6 @@ export class SidebarStore { this._networkSet.clear(); this._notableChannelSet.clear(); this._unreadCount.clear(); - - this._updater = null; - this._disposer = null; - this._currentId = null; - this._networkSet = null; - this._notableChannelSet = null; - this._unreadCount = null; - this._state = null; } private _addNetwork(network: Network): void { @@ -193,7 +185,7 @@ export class SidebarStore { return false; } - const current: number = this._unreadCount.get(channelId); + const current: number | void = this._unreadCount.get(channelId); if (current === undefined) { this._unreadCount.set(channelId, 0); }