refactor: enable TypeScript strict-mode

This commit is contained in:
mathuo 2020-12-22 15:15:46 +00:00
parent a3776e9d6c
commit 723299aac9
26 changed files with 99 additions and 94 deletions

View File

@ -11,13 +11,7 @@
"noImplicitAny": true,
"allowUnreachableCode": false,
"forceConsistentCasingInFileNames": true,
// "strict": true,
"strictBindCallApply": true, // pass
"alwaysStrict": true, // pass
"noImplicitThis": true, // pass
"strictFunctionTypes": true, // pass
"strictNullChecks": false,
"strictPropertyInitialization": false,
"strict": true,
"lib": [
"ES2015",
"ES2016.Array.Include",

View File

@ -11,13 +11,7 @@
"noImplicitAny": true,
"allowUnreachableCode": false,
"forceConsistentCasingInFileNames": true,
// "strict": true,
"strictBindCallApply": true, // pass
"alwaysStrict": true, // pass
"noImplicitThis": true, // pass
"strictFunctionTypes": true, // pass
"strictNullChecks": false,
"strictPropertyInitialization": false,
"strict": true,
"lib": [
"ES2015",
"ES2016.Array.Include",

View File

@ -21,7 +21,6 @@
"rebuild": "npm run clean && npm run build",
"test": "cross-env ../../node_modules/.bin/jest --selectProjects dockview",
"test-cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage",
"try-strict": "cross-env ../../node_modules/.bin/tsc --project tsconfig.strictNullChecks.json --extendedDiagnostics",
"preversion": "npm run rebuild && npm run test"
},
"files": [

View File

@ -8,10 +8,11 @@ import {
IPaneHeaderPart,
PanePanelComponentInitParameter,
} from '../../paneview/paneviewPanel';
import { Orientation } from '../../splitview/core/splitview';
class TestPanel extends PaneviewPanel {
constructor(id: string, component: string) {
super(id, component, 'header');
super(id, component, 'header', Orientation.VERTICAL);
}
getHeaderComponent() {

View File

@ -14,17 +14,17 @@ export interface TitleEvent {
*/
export interface IGroupPanelApi
extends Omit<IGridPanelApi, 'setVisible' | 'visible'> {
readonly group: IGroupview;
readonly group: IGroupview | undefined;
readonly isGroupActive: boolean;
onDidDirtyChange: Event<boolean>;
close: () => Promise<boolean>;
tryClose: () => Promise<boolean>;
tryClose: undefined | (() => Promise<boolean>);
interceptOnCloseAction(interceptor: () => Promise<boolean>): void;
setTitle(title: string): void;
}
export class GroupPanelApi extends GridPanelApi implements IGroupPanelApi {
private _group: IGroupview;
private _group: IGroupview | undefined;
private _interceptor: undefined | (() => Promise<boolean>);
readonly _onDidDirtyChange = new Emitter<boolean>();
@ -41,23 +41,23 @@ export class GroupPanelApi extends GridPanelApi implements IGroupPanelApi {
// return this._isGroupVisible;
// }
get tryClose() {
get tryClose(): undefined | (() => Promise<boolean>) {
return this._interceptor;
}
get isGroupActive() {
return this.group.isActive;
return !!this.group?.isActive;
}
set group(value: IGroupview) {
set group(value: IGroupview | undefined) {
this._group = value;
}
get group() {
get group(): IGroupview | undefined {
return this._group;
}
constructor(private panel: IGroupPanel, group: IGroupview) {
constructor(private panel: IGroupPanel, group: IGroupview | undefined) {
super(panel.id);
this._group = group;
@ -74,7 +74,10 @@ export class GroupPanelApi extends GridPanelApi implements IGroupPanelApi {
this._onDidTitleChange.fire({ title });
}
public close() {
public close(): Promise<boolean> {
if (!this.group) {
throw new Error(`panel ${this.id} has no group`);
}
return this.group.closePanel(this.panel);
}

View File

@ -26,7 +26,7 @@ export class PanePanelApi extends PanelApi implements IPanePanelApi {
readonly _onMouseLeave = new Emitter<MouseEvent>({});
readonly onMouseLeave: Event<MouseEvent> = this._onMouseLeave.event;
private _pane: PaneviewPanel;
private _pane: PaneviewPanel | undefined;
set pane(pane: PaneviewPanel) {
this._pane = pane;
@ -37,10 +37,10 @@ export class PanePanelApi extends PanelApi implements IPanePanelApi {
}
setExpanded(isExpanded: boolean): void {
this._pane.setExpanded(isExpanded);
this._pane?.setExpanded(isExpanded);
}
get isExpanded() {
return this._pane.isExpanded();
get isExpanded(): boolean {
return !!this._pane?.isExpanded();
}
}

View File

@ -10,8 +10,8 @@ import { CompositeDisposable } from '../../../lifecycle';
export class Watermark extends CompositeDisposable implements WatermarkPart {
private _element: HTMLElement;
private group: IGroupview;
private params: GroupPanelPartInitParameters;
private group: IGroupview | undefined;
private params: GroupPanelPartInitParameters | undefined;
get id() {
return 'watermark';
@ -46,7 +46,9 @@ export class Watermark extends CompositeDisposable implements WatermarkPart {
this.addDisposables(
addDisposableListener(closeAnchor, 'click', (ev) => {
ev.preventDefault();
this.params.containerApi.removeGroup(this.group);
if (this.group) {
this.params?.containerApi.removeGroup(this.group);
}
})
);
}
@ -77,7 +79,9 @@ export class Watermark extends CompositeDisposable implements WatermarkPart {
}
private render() {
const isOneGroup = this.params.containerApi.size <= 1;
const isOneGroup = !!(
this.params && this.params.containerApi.size <= 1
);
toggleClass(this.element, 'has-actions', isOneGroup);
}

View File

@ -60,6 +60,7 @@ import { State } from '../api/api';
import { LayoutMouseEvent, MouseEventKind } from '../groupview/tab';
import { Orientation } from '../splitview/core/splitview';
import { DefaultTab } from './components/tab/defaultTab';
import { IGroupPanelApi } from '../api/groupPanelApi';
const nextGroupId = sequentialNumberGenerator();
@ -102,7 +103,7 @@ export interface IDockviewComponent extends IBaseGrid<IGroupview> {
// lifecycle
addEmptyGroup(options?: AddGroupOptions): void;
closeAllGroups: () => Promise<boolean>;
deserializer: IPanelDeserializer;
deserializer: IPanelDeserializer | undefined;
// events
onTabInteractionEvent: Event<LayoutMouseEvent>;
onTabContextMenu: Event<TabContextMenuEvent>;
@ -148,7 +149,7 @@ export class DockviewComponent
._onTabContextMenu.event;
// everything else
private drag = new MutableDisposable();
private _deserializer: IPanelDeserializer;
private _deserializer: IPanelDeserializer | undefined;
private panelState: State = {};
private registry = new Map<
string,
@ -233,11 +234,11 @@ export class DockviewComponent
return this.panels.size;
}
get deserializer(): IPanelDeserializer {
get deserializer(): IPanelDeserializer | undefined {
return this._deserializer;
}
set deserializer(value: IPanelDeserializer) {
set deserializer(value: IPanelDeserializer | undefined) {
this._deserializer = value;
}
@ -473,12 +474,16 @@ export class DockviewComponent
this.setTabHeight(options.tabHeight);
}
if (!this.deserializer) {
throw new Error('no deserializer provided');
}
this.gridview.deserialize(
grid,
new DefaultDeserializer(this, {
createPanel: (id) => {
const panelData = panels[id];
const panel = this.deserializer.fromJSON(panelData);
const panel = this.deserializer!.fromJSON(panelData);
this.registerPanel(panel);
return panel;
},
@ -586,7 +591,7 @@ export class DockviewComponent
options.tabComponent
);
const panel = new GroupviewPanel(options.id, this._api);
const panel: IGroupPanel = new GroupviewPanel(options.id, this._api);
panel.init({
headerPart,
contentPart,

View File

@ -252,7 +252,7 @@ export interface IViewDeserializer {
}
export class Gridview implements IDisposable {
private _root: BranchNode;
private _root: BranchNode | undefined;
public readonly element: HTMLElement;
private disposable: MutableDisposable = new MutableDisposable();
@ -357,17 +357,17 @@ export class Gridview implements IDisposable {
}
public set orientation(orientation: Orientation) {
if (this._root.orientation === orientation) {
if (this.root.orientation === orientation) {
return;
}
const { size, orthogonalSize } = this._root;
this.root = flipNode(this._root, orthogonalSize, size);
const { size, orthogonalSize } = this.root;
this.root = flipNode(this.root, orthogonalSize, size);
this.root.layout(size, orthogonalSize);
}
private get root(): BranchNode {
return this._root;
return this._root!;
}
private set root(root: BranchNode) {
@ -396,7 +396,7 @@ export class Gridview implements IDisposable {
getView(): GridBranchNode<IGridView>;
getView(location?: number[]): GridNode<IGridView>;
getView(location?: number[]): GridNode<IGridView> {
const node = location ? this.getNode(location)[1] : this._root;
const node = location ? this.getNode(location)[1] : this.root;
return this._getViews(node, this.orientation);
}

View File

@ -24,7 +24,6 @@ import { GridPanelApi } from '../api/gridPanelApi';
import { GridviewApi } from '../api/component.api';
import { Orientation, Sizing } from '../splitview/core/splitview';
import { createComponent } from '../panel/componentFactory';
import { Event } from '../events';
interface PanelReference {
api: GridPanelApi;
@ -76,7 +75,7 @@ export interface IGridviewComponent extends IBaseGrid<GridviewPanel> {
export class GridviewComponent
extends BaseGrid<GridviewPanel>
implements IGridviewComponent {
private _deserializer: IPanelDeserializer;
private _deserializer: IPanelDeserializer | undefined;
constructor(
element: HTMLElement,
@ -105,11 +104,11 @@ export class GridviewComponent
this.layout(this.gridview.width, this.gridview.height, true);
}
get deserializer() {
get deserializer(): IPanelDeserializer | undefined {
return this._deserializer;
}
set deserializer(value: IPanelDeserializer) {
set deserializer(value: IPanelDeserializer | undefined) {
this._deserializer = value;
}

View File

@ -160,7 +160,7 @@ export class GroupviewPanel extends CompositeDisposable implements IGroupPanel {
this.mutableDisposable.value = this._group.onDidGroupChange((ev) => {
if (ev.kind === GroupChangeKind.GROUP_ACTIVE) {
const isPanelVisible = this._group.isPanelActive(this);
const isPanelVisible = !!this._group?.isPanelActive(this);
this.api._onDidActiveChange.fire({
isActive: isGroupActive && isPanelVisible,
});

View File

@ -9,7 +9,7 @@ import { IGroupPanel } from './groupviewPanel';
interface IGroupApi extends IGridPanelApi {}
class GroupApi extends GridPanelApi implements IGroupApi {
private _value: GroupComponent;
private _value?: GroupComponent;
set group(value: GroupComponent) {
this._value = value;

View File

@ -43,7 +43,7 @@ export class Tab extends CompositeDisposable implements ITab {
isDragging: false,
};
private droptarget: Droptarget;
private content: PanelHeaderPart;
private content?: PanelHeaderPart;
private readonly _onChanged = new Emitter<LayoutMouseEvent>();
readonly onChanged: Event<LayoutMouseEvent> = this._onChanged.event;

View File

@ -1,3 +1,4 @@
import { Orientation } from '../splitview/core/splitview';
import { FrameworkFactory } from '../types';
export function createComponent<T>(

View File

@ -78,9 +78,15 @@ export class PaneFramework extends PaneviewPanel {
headerComponent: string | undefined;
body: IPaneBodyPart;
header: IPaneHeaderPart;
orientation: Orientation;
}
) {
super(options.id, options.component, options.headerComponent);
super(
options.id,
options.component,
options.headerComponent,
options.orientation
);
}
getBodyComponent() {
@ -220,6 +226,7 @@ export class PaneviewComponent
headerComponent: options.headerComponent,
header,
body,
orientation: Orientation.VERTICAL,
});
const size: Sizing | number =
@ -359,6 +366,7 @@ export class PaneviewComponent
headerComponent: data.headerComponent,
header,
body,
orientation: Orientation.VERTICAL,
});
queue.push(() => {
@ -372,8 +380,6 @@ export class PaneviewComponent
});
});
panel.orientation = Orientation.VERTICAL;
return { size: view.size, view: panel };
}),
},

View File

@ -71,11 +71,11 @@ export abstract class PaneviewPanel
private _minimumBodySize = 0;
private _maximumBodySize: number = Number.POSITIVE_INFINITY;
private _isExpanded = false;
protected header: HTMLElement;
protected body: HTMLElement;
protected header?: HTMLElement;
protected body?: HTMLElement;
private bodyPart?: IPaneHeaderPart;
private headerPart?: IPaneBodyPart;
private expandedSize: number;
private expandedSize = 0;
private animationTimer: any | undefined;
private _orientation: Orientation;
@ -124,11 +124,14 @@ export abstract class PaneviewPanel
constructor(
id: string,
component: string,
private readonly headerComponent: string | undefined
private readonly headerComponent: string | undefined,
orientation: Orientation
) {
super(id, component, new PanePanelApi(id));
this.api.pane = this; // TODO cannot use 'this' before 'super'
this._orientation = orientation;
this.element.classList.add('pane');
this.addDisposables(
@ -180,10 +183,12 @@ export abstract class PaneviewPanel
if (this.animationTimer) {
clearTimeout(this.animationTimer);
}
this.element.appendChild(this.body);
if (this.body) {
this.element.appendChild(this.body);
}
} else {
this.animationTimer = setTimeout(() => {
this.body.remove();
this.body?.remove();
}, 200);
}
@ -218,8 +223,8 @@ export abstract class PaneviewPanel
this.bodyPart.init({ ...parameters, api: this.api });
this.headerPart.init({ ...parameters, api: this.api });
this.body.append(this.bodyPart.element);
this.header.append(this.headerPart.element);
this.body?.append(this.bodyPart.element);
this.header?.append(this.headerPart.element);
if (typeof parameters.isExpanded === 'boolean') {
this.setExpanded(parameters.isExpanded);

View File

@ -74,7 +74,7 @@ export const DockviewReact: React.FunctionComponent<IDockviewReactProps> = (
};
}
const watcher = watchElementResize(domRef.current, (entry) => {
const watcher = watchElementResize(domRef.current!, (entry) => {
const { width, height } = entry.contentRect;
dockviewRef.current?.layout(width, height);
});

View File

@ -18,18 +18,18 @@ export interface IGroupPanelActionbarProps {
export class ReactPanelContentPart implements PanelContentPart {
private _element: HTMLElement;
private part?: ReactPart<IDockviewPanelProps>;
private _group: IGroupview;
private _group: IGroupview | undefined;
//
private _actionsElement: HTMLElement;
private actionsPart?: ReactPart<any>;
private parameters: GroupPanelPartInitParameters;
private parameters: GroupPanelPartInitParameters | undefined;
get element() {
get element(): HTMLElement {
return this._element;
}
get actions() {
get actions(): HTMLElement {
return this._actionsElement;
}
@ -82,8 +82,8 @@ export class ReactPanelContentPart implements PanelContentPart {
component,
{
...props,
api: this.parameters.api,
containerApi: this.parameters.containerApi,
api: this.parameters!.api,
containerApi: this.parameters!.containerApi,
}
);
@ -107,7 +107,10 @@ export class ReactPanelContentPart implements PanelContentPart {
}
public update(params: PanelUpdateEvent) {
this.parameters.params = params.params;
if (this.parameters) {
this.parameters.params = params.params;
}
this.part?.update(params.params);
}

View File

@ -45,7 +45,7 @@ export const GridviewReact: React.FunctionComponent<IGridviewReactProps> = (
};
}
const watcher = watchElementResize(domRef.current, (entry) => {
const watcher = watchElementResize(domRef.current!, (entry) => {
const { width, height } = entry.contentRect;
gridviewRef.current?.layout(width, height);
});

View File

@ -43,7 +43,7 @@ export const PaneviewReact: React.FunctionComponent<IPaneviewReactProps> = (
};
}
const watcher = watchElementResize(domRef.current, (entry) => {
const watcher = watchElementResize(domRef.current!, (entry) => {
const { width, height } = entry.contentRect;
paneviewRef.current?.layout(width, height);
});

View File

@ -68,7 +68,7 @@ ReactComponentBridge.displayName = 'PanelWrapper';
const uniquePortalKeyGenerator = sequentialNumberGenerator();
export class ReactPart<P extends object> implements IFrameworkPart {
private componentInstance: IPanelWrapperRef;
private componentInstance?: IPanelWrapperRef;
private ref?: { portal: React.ReactPortal; disposable: IDisposable };
private disposed = false;

View File

@ -45,7 +45,7 @@ export const SplitviewReact: React.FunctionComponent<ISplitviewReactProps> = (
};
}
const watcher = watchElementResize(domRef.current, (entry) => {
const watcher = watchElementResize(domRef.current!, (entry) => {
const { width, height } = entry.contentRect;
splitviewRef.current?.layout(width, height);
});

View File

@ -1,5 +1,10 @@
import { IPanel, PanelInitParameters } from '../../panel/types';
import { IView, SplitViewOptions, LayoutPriority } from './splitview';
import {
IView,
SplitViewOptions,
LayoutPriority,
Orientation,
} from './splitview';
import { Constructor, FrameworkFactory } from '../../types';
import { SplitviewPanel } from '../splitviewPanel';
import { SplitviewApi } from '../../api/component.api';

View File

@ -31,7 +31,7 @@ export interface SerializedSplitviewPanel {
export interface SerializedSplitview {
orientation: Orientation;
size: number;
activeView: string;
activeView?: string;
views: SerializedSplitviewPanel[];
}
@ -70,7 +70,7 @@ export class SplitviewComponent
extends CompositeDisposable
implements ISplitviewComponent {
private splitview: Splitview;
private _activePanel: SplitviewPanel;
private _activePanel: SplitviewPanel | undefined;
private panels = new Map<string, IDisposable>();
private readonly _onDidLayoutChange = new Emitter<void>();

View File

@ -27,7 +27,7 @@ export abstract class SplitviewPanel
private _priority?: LayoutPriority;
private _snap = false;
private _orientation: Orientation;
private _orientation?: Orientation;
private readonly _onDidChange = new Emitter<number | undefined>();
readonly onDidChange: Event<number | undefined> = this._onDidChange.event;
@ -41,7 +41,7 @@ export abstract class SplitviewPanel
}
get orientation(): Orientation {
return this._orientation;
return this._orientation!;
}
get minimumSize(): number {

View File

@ -1,14 +0,0 @@
{
"extends": "./tsconfig.es6.json",
"compilerOptions": {
"noEmit": true,
"strictNullChecks": true
},
"include": [
"src"
],
"exclude": [
"**/node_modules",
"src/__tests__"
]
}