Skip to content

Commit ecc0797

Browse files
committed
refactor(@angular-devkit/schematics): support isolatedDeclarations for tree classes
This commit refactors several Tree implementations (`DelegateTree`, `HostTree`, `NullTree`, `ScopedTree`) to support the TypeScript `isolatedDeclarations` compiler option. It uses declaration merging to define the `[TreeSymbol]` method on an interface and assigns it in the constructor to avoid TS9038 errors regarding computed property names inference.
1 parent f9507ff commit ecc0797

File tree

5 files changed

+53
-17
lines changed

5 files changed

+53
-17
lines changed

goldens/public-api/angular_devkit/schematics/index.api.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,14 @@ export interface CreateFileAction extends ActionBase {
202202
readonly kind: 'c';
203203
}
204204

205+
// @public (undocumented)
206+
export interface DelegateTree {
207+
}
208+
205209
// @public (undocumented)
206210
export class DelegateTree implements Tree_2 {
207211
// (undocumented)
208-
[TreeSymbol]: () => this;
212+
[TreeSymbol]: () => DelegateTree;
209213
constructor(_other: Tree_2);
210214
// (undocumented)
211215
get actions(): Action[];
@@ -516,10 +520,14 @@ export class HostSink extends SimpleSinkBase {
516520
protected _validateFileExists(p: Path): Observable<boolean>;
517521
}
518522

523+
// @public (undocumented)
524+
export interface HostTree {
525+
}
526+
519527
// @public (undocumented)
520528
export class HostTree implements Tree_2 {
521529
// (undocumented)
522-
[TreeSymbol]: () => this;
530+
[TreeSymbol]: () => HostTree;
523531
constructor(_backend?: virtualFs.ReadonlyHost<{}>);
524532
// (undocumented)
525533
get actions(): Action[];

packages/angular_devkit/schematics/src/tree/delegate.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,19 @@ import {
1818
UpdateRecorder,
1919
} from './interface';
2020

21+
// Workaround for "error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations."
22+
// When this is fixed within TypeScript, the method can be added back directly to the class.
23+
// See: https://github.com/microsoft/TypeScript/issues/61892
24+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
25+
export interface DelegateTree {
26+
[TreeSymbol](): DelegateTree;
27+
}
28+
29+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
2130
export class DelegateTree implements Tree {
22-
constructor(protected _other: Tree) {}
31+
constructor(protected _other: Tree) {
32+
this[TreeSymbol] = () => this;
33+
}
2334

2435
branch(): Tree {
2536
return this._other.branch();
@@ -83,8 +94,4 @@ export class DelegateTree implements Tree {
8394
get actions(): Action[] {
8495
return this._other.actions;
8596
}
86-
87-
[TreeSymbol]() {
88-
return this;
89-
}
9097
}

packages/angular_devkit/schematics/src/tree/host-tree.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,15 @@ export class HostDirEntry implements DirEntry {
9898
}
9999
}
100100

101+
// Workaround for "error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations."
102+
// When this is fixed within TypeScript, the method can be added back directly to the class.
103+
// See: https://github.com/microsoft/TypeScript/issues/61892
104+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
105+
export interface HostTree {
106+
[TreeSymbol](): HostTree;
107+
}
108+
109+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
101110
export class HostTree implements Tree {
102111
private readonly _id = --_uniqueId;
103112
private _record: virtualFs.CordHost;
@@ -106,10 +115,6 @@ export class HostTree implements Tree {
106115

107116
private _dirCache = new Map<Path, HostDirEntry>();
108117

109-
[TreeSymbol](): this {
110-
return this;
111-
}
112-
113118
static isHostTree(tree: Tree): tree is HostTree {
114119
if (tree instanceof HostTree) {
115120
return true;
@@ -123,6 +128,7 @@ export class HostTree implements Tree {
123128
}
124129

125130
constructor(protected _backend: virtualFs.ReadonlyHost<{}> = new virtualFs.Empty()) {
131+
this[TreeSymbol] = () => this;
126132
this._record = new virtualFs.CordHost(new virtualFs.SafeReadonlyHost(_backend));
127133
this._recordSync = new virtualFs.SyncDelegateHost(this._record);
128134
}

packages/angular_devkit/schematics/src/tree/null.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,18 @@ export class NullTreeDirEntry implements DirEntry {
4646
visit(): void {}
4747
}
4848

49+
// Workaround for "error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations."
50+
// When this is fixed within TypeScript, the method can be added back directly to the class.
51+
// See: https://github.com/microsoft/TypeScript/issues/61892
52+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
53+
export interface NullTree {
54+
[TreeSymbol](): NullTree;
55+
}
56+
57+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
4958
export class NullTree implements Tree {
50-
[TreeSymbol](): this {
51-
return this;
59+
constructor() {
60+
this[TreeSymbol] = () => this;
5261
}
5362

5463
branch(): Tree {

packages/angular_devkit/schematics/src/tree/scoped.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,23 @@ class ScopedDirEntry implements DirEntry {
8989
}
9090
}
9191

92+
// Workaround for "error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations."
93+
// When this is fixed within TypeScript, the method can be added back directly to the class.
94+
// See: https://github.com/microsoft/TypeScript/issues/61892
95+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
96+
export interface ScopedTree {
97+
[TreeSymbol](): ScopedTree;
98+
}
99+
100+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
92101
export class ScopedTree implements Tree {
93102
readonly _root: ScopedDirEntry;
94103

95104
constructor(
96105
private _base: Tree,
97106
scope: string,
98107
) {
108+
this[TreeSymbol] = () => this;
99109
const normalizedScope = normalize('/' + scope);
100110
this._root = new ScopedDirEntry(this._base.getDir(normalizedScope), normalizedScope);
101111
}
@@ -197,10 +207,6 @@ export class ScopedTree implements Tree {
197207
return scopedActions;
198208
}
199209

200-
[TreeSymbol](): this {
201-
return this;
202-
}
203-
204210
private _fullPath(path: string): Path {
205211
return join(this._root.scope, normalize('/' + path));
206212
}

0 commit comments

Comments
 (0)