Skip to content

Commit 1bb6ea0

Browse files
authored
Allow type-only namespace imports in implements clauses (microsoft#36464)
* Add test * Allow type-only symbols in implements clauses * Add more complex test
1 parent a87512d commit 1bb6ea0

File tree

5 files changed

+114
-0
lines changed

5 files changed

+114
-0
lines changed

src/compiler/utilities.ts

+6
Original file line numberDiff line numberDiff line change
@@ -1792,6 +1792,11 @@ namespace ts {
17921792
return containerKind === SyntaxKind.InterfaceDeclaration || containerKind === SyntaxKind.TypeLiteral;
17931793
}
17941794

1795+
export function isFirstIdentifierOfImplementsClause(node: Node) {
1796+
return node.parent?.parent?.parent?.kind === SyntaxKind.HeritageClause
1797+
&& (node.parent.parent.parent as HeritageClause).token === SyntaxKind.ImplementsKeyword;
1798+
}
1799+
17951800
export function isExternalModuleImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration & { moduleReference: ExternalModuleReference } {
17961801
return node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference;
17971802
}
@@ -6138,6 +6143,7 @@ namespace ts {
61386143
export function isValidTypeOnlyAliasUseSite(useSite: Node): boolean {
61396144
return !!(useSite.flags & NodeFlags.Ambient)
61406145
|| isPartOfTypeQuery(useSite)
6146+
|| isFirstIdentifierOfImplementsClause(useSite)
61416147
|| isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(useSite)
61426148
|| !isExpressionNode(useSite);
61436149
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//// [tests/cases/conformance/externalModules/typeOnly/implementsClause.ts] ////
2+
3+
//// [types.ts]
4+
export interface Component {}
5+
6+
//// [ns.ts]
7+
import type * as types from './types';
8+
export { types };
9+
10+
//// [index.ts]
11+
import type * as types from './types';
12+
import * as nestedNamespace from './ns';
13+
14+
class C implements types.Component {}
15+
class D implements nestedNamespace.types.Component {}
16+
17+
18+
//// [types.js]
19+
"use strict";
20+
exports.__esModule = true;
21+
//// [ns.js]
22+
"use strict";
23+
exports.__esModule = true;
24+
//// [index.js]
25+
"use strict";
26+
exports.__esModule = true;
27+
var C = /** @class */ (function () {
28+
function C() {
29+
}
30+
return C;
31+
}());
32+
var D = /** @class */ (function () {
33+
function D() {
34+
}
35+
return D;
36+
}());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
=== tests/cases/conformance/externalModules/typeOnly/types.ts ===
2+
export interface Component {}
3+
>Component : Symbol(Component, Decl(types.ts, 0, 0))
4+
5+
=== tests/cases/conformance/externalModules/typeOnly/ns.ts ===
6+
import type * as types from './types';
7+
>types : Symbol(types, Decl(ns.ts, 0, 11))
8+
9+
export { types };
10+
>types : Symbol(types, Decl(ns.ts, 1, 8))
11+
12+
=== tests/cases/conformance/externalModules/typeOnly/index.ts ===
13+
import type * as types from './types';
14+
>types : Symbol(types, Decl(index.ts, 0, 11))
15+
16+
import * as nestedNamespace from './ns';
17+
>nestedNamespace : Symbol(nestedNamespace, Decl(index.ts, 1, 6))
18+
19+
class C implements types.Component {}
20+
>C : Symbol(C, Decl(index.ts, 1, 40))
21+
>types.Component : Symbol(types.Component, Decl(types.ts, 0, 0))
22+
>types : Symbol(types, Decl(index.ts, 0, 11))
23+
>Component : Symbol(types.Component, Decl(types.ts, 0, 0))
24+
25+
class D implements nestedNamespace.types.Component {}
26+
>D : Symbol(D, Decl(index.ts, 3, 37))
27+
>nestedNamespace.types.Component : Symbol(types.Component, Decl(types.ts, 0, 0))
28+
>nestedNamespace.types : Symbol(nestedNamespace.types, Decl(ns.ts, 1, 8))
29+
>nestedNamespace : Symbol(nestedNamespace, Decl(index.ts, 1, 6))
30+
>types : Symbol(nestedNamespace.types, Decl(ns.ts, 1, 8))
31+
>Component : Symbol(types.Component, Decl(types.ts, 0, 0))
32+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/conformance/externalModules/typeOnly/types.ts ===
2+
export interface Component {}
3+
No type information for this code.
4+
No type information for this code.=== tests/cases/conformance/externalModules/typeOnly/ns.ts ===
5+
import type * as types from './types';
6+
>types : typeof types
7+
8+
export { types };
9+
>types : typeof types
10+
11+
=== tests/cases/conformance/externalModules/typeOnly/index.ts ===
12+
import type * as types from './types';
13+
>types : typeof types
14+
15+
import * as nestedNamespace from './ns';
16+
>nestedNamespace : typeof nestedNamespace
17+
18+
class C implements types.Component {}
19+
>C : C
20+
>types : typeof types
21+
22+
class D implements nestedNamespace.types.Component {}
23+
>D : D
24+
>nestedNamespace.types : any
25+
>nestedNamespace : typeof nestedNamespace
26+
>types : any
27+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// @Filename: types.ts
2+
export interface Component {}
3+
4+
// @Filename: ns.ts
5+
import type * as types from './types';
6+
export { types };
7+
8+
// @Filename: index.ts
9+
import type * as types from './types';
10+
import * as nestedNamespace from './ns';
11+
12+
class C implements types.Component {}
13+
class D implements nestedNamespace.types.Component {}

0 commit comments

Comments
 (0)