Fix interface extends clause

This commit is contained in:
Andrew Branch
2020-01-28 11:33:42 -08:00
parent 2e47d4a132
commit 7e1382aa1a
6 changed files with 209 additions and 4 deletions

View File

@@ -1792,9 +1792,10 @@ namespace ts {
return containerKind === SyntaxKind.InterfaceDeclaration || containerKind === SyntaxKind.TypeLiteral;
}
export function isFirstIdentifierOfImplementsClause(node: Node) {
return node.parent?.parent?.parent?.kind === SyntaxKind.HeritageClause
&& (node.parent.parent.parent as HeritageClause).token === SyntaxKind.ImplementsKeyword;
export function isFirstIdentifierOfNonEmittingHeritageClause(node: Node): boolean {
// Number of parents to climb from identifier is 2 for `implements I`, 3 for `implements x.I`
const heritageClause = tryCast(node.parent.parent, isHeritageClause) ?? tryCast(node.parent.parent.parent, isHeritageClause);
return heritageClause?.token === SyntaxKind.ImplementsKeyword || heritageClause?.parent.kind === SyntaxKind.InterfaceDeclaration;
}
export function isExternalModuleImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration & { moduleReference: ExternalModuleReference } {
@@ -6143,7 +6144,7 @@ namespace ts {
export function isValidTypeOnlyAliasUseSite(useSite: Node): boolean {
return !!(useSite.flags & NodeFlags.Ambient)
|| isPartOfTypeQuery(useSite)
|| isFirstIdentifierOfImplementsClause(useSite)
|| isFirstIdentifierOfNonEmittingHeritageClause(useSite)
|| isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(useSite)
|| !isExpressionNode(useSite);
}

View File

@@ -0,0 +1,30 @@
tests/cases/conformance/externalModules/typeOnly/index.ts(9,17): error TS1361: 'C' cannot be used as a value because it was imported using 'import type'.
tests/cases/conformance/externalModules/typeOnly/index.ts(10,17): error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
==== tests/cases/conformance/externalModules/typeOnly/types.ts (0 errors) ====
export interface I {}
export class C {}
==== tests/cases/conformance/externalModules/typeOnly/ns.ts (0 errors) ====
import type * as types from './types';
export { types };
==== tests/cases/conformance/externalModules/typeOnly/index.ts (2 errors) ====
import { types } from './ns';
import type { C, I } from './types';
interface Q extends C {}
interface R extends I {}
interface S extends types.C {}
interface T extends types.I {}
class U extends C {} // Error
~
!!! error TS1361: 'C' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 tests/cases/conformance/externalModules/typeOnly/index.ts:2:15: 'C' was imported here.
class V extends types.C {} // Error
~~~~~
!!! error TS1361: 'types' cannot be used as a value because it was imported using 'import type'.
!!! related TS1376 tests/cases/conformance/externalModules/typeOnly/ns.ts:1:13: 'types' was imported here.

View File

@@ -0,0 +1,65 @@
//// [tests/cases/conformance/externalModules/typeOnly/extendsClause.ts] ////
//// [types.ts]
export interface I {}
export class C {}
//// [ns.ts]
import type * as types from './types';
export { types };
//// [index.ts]
import { types } from './ns';
import type { C, I } from './types';
interface Q extends C {}
interface R extends I {}
interface S extends types.C {}
interface T extends types.I {}
class U extends C {} // Error
class V extends types.C {} // Error
//// [types.js]
"use strict";
exports.__esModule = true;
var C = /** @class */ (function () {
function C() {
}
return C;
}());
exports.C = C;
//// [ns.js]
"use strict";
exports.__esModule = true;
//// [index.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var U = /** @class */ (function (_super) {
__extends(U, _super);
function U() {
return _super !== null && _super.apply(this, arguments) || this;
}
return U;
}(C)); // Error
var V = /** @class */ (function (_super) {
__extends(V, _super);
function V() {
return _super !== null && _super.apply(this, arguments) || this;
}
return V;
}(types.C)); // Error

View File

@@ -0,0 +1,52 @@
=== tests/cases/conformance/externalModules/typeOnly/types.ts ===
export interface I {}
>I : Symbol(I, Decl(types.ts, 0, 0))
export class C {}
>C : Symbol(C, Decl(types.ts, 0, 21))
=== tests/cases/conformance/externalModules/typeOnly/ns.ts ===
import type * as types from './types';
>types : Symbol(types, Decl(ns.ts, 0, 11))
export { types };
>types : Symbol(types, Decl(ns.ts, 1, 8))
=== tests/cases/conformance/externalModules/typeOnly/index.ts ===
import { types } from './ns';
>types : Symbol(types, Decl(index.ts, 0, 8))
import type { C, I } from './types';
>C : Symbol(C, Decl(index.ts, 1, 13))
>I : Symbol(I, Decl(index.ts, 1, 16))
interface Q extends C {}
>Q : Symbol(Q, Decl(index.ts, 1, 36))
>C : Symbol(C, Decl(index.ts, 1, 13))
interface R extends I {}
>R : Symbol(R, Decl(index.ts, 3, 24))
>I : Symbol(I, Decl(index.ts, 1, 16))
interface S extends types.C {}
>S : Symbol(S, Decl(index.ts, 4, 24))
>types.C : Symbol(types.C, Decl(types.ts, 0, 21))
>types : Symbol(types, Decl(index.ts, 0, 8))
>C : Symbol(types.C, Decl(types.ts, 0, 21))
interface T extends types.I {}
>T : Symbol(T, Decl(index.ts, 5, 30))
>types.I : Symbol(types.I, Decl(types.ts, 0, 0))
>types : Symbol(types, Decl(index.ts, 0, 8))
>I : Symbol(types.I, Decl(types.ts, 0, 0))
class U extends C {} // Error
>U : Symbol(U, Decl(index.ts, 6, 30))
>C : Symbol(C, Decl(index.ts, 1, 13))
class V extends types.C {} // Error
>V : Symbol(V, Decl(index.ts, 8, 20))
>types.C : Symbol(types.C, Decl(types.ts, 0, 21))
>types : Symbol(types, Decl(index.ts, 0, 8))
>C : Symbol(types.C, Decl(types.ts, 0, 21))

View File

@@ -0,0 +1,38 @@
=== tests/cases/conformance/externalModules/typeOnly/types.ts ===
export interface I {}
export class C {}
>C : C
=== tests/cases/conformance/externalModules/typeOnly/ns.ts ===
import type * as types from './types';
>types : typeof types
export { types };
>types : typeof types
=== tests/cases/conformance/externalModules/typeOnly/index.ts ===
import { types } from './ns';
>types : typeof types
import type { C, I } from './types';
>C : types.C
>I : types.I
interface Q extends C {}
interface R extends I {}
interface S extends types.C {}
>types : typeof types
interface T extends types.I {}
>types : typeof types
class U extends C {} // Error
>U : U
>C : types.C
class V extends types.C {} // Error
>V : V
>types.C : types.C
>types : typeof types
>C : typeof types.C

View File

@@ -0,0 +1,19 @@
// @Filename: types.ts
export interface I {}
export class C {}
// @Filename: ns.ts
import type * as types from './types';
export { types };
// @Filename: index.ts
import { types } from './ns';
import type { C, I } from './types';
interface Q extends C {}
interface R extends I {}
interface S extends types.C {}
interface T extends types.I {}
class U extends C {} // Error
class V extends types.C {} // Error