Skip to content

Commit b1fac59

Browse files
committed
Merge pull request microsoft#5934 from Microsoft/inherit-construct-signature-from-extended-interface
Inherit construct signature from extended interface
2 parents 9b441d8 + e2b6898 commit b1fac59

6 files changed

Lines changed: 94 additions & 14 deletions

src/compiler/checker.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2990,10 +2990,6 @@ namespace ts {
29902990
return type.resolvedBaseConstructorType;
29912991
}
29922992

2993-
function hasClassBaseType(type: InterfaceType): boolean {
2994-
return !!forEach(getBaseTypes(type), t => !!(t.symbol.flags & SymbolFlags.Class));
2995-
}
2996-
29972993
function getBaseTypes(type: InterfaceType): ObjectType[] {
29982994
const isClass = type.symbol.flags & SymbolFlags.Class;
29992995
const isInterface = type.symbol.flags & SymbolFlags.Interface;
@@ -3427,11 +3423,11 @@ namespace ts {
34273423
}
34283424

34293425
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
3430-
if (!hasClassBaseType(classType)) {
3431-
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
3432-
}
34333426
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
34343427
const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
3428+
if (baseSignatures.length === 0) {
3429+
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
3430+
}
34353431
const baseTypeNode = getBaseTypeNodeOfClass(classType);
34363432
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
34373433
const typeArgCount = typeArguments ? typeArguments.length : 0;
@@ -3649,16 +3645,16 @@ namespace ts {
36493645
return <ResolvedType>type;
36503646
}
36513647

3652-
// Return properties of an object type or an empty array for other types
3648+
/** Return properties of an object type or an empty array for other types */
36533649
function getPropertiesOfObjectType(type: Type): Symbol[] {
36543650
if (type.flags & TypeFlags.ObjectType) {
36553651
return resolveStructuredTypeMembers(<ObjectType>type).properties;
36563652
}
36573653
return emptyArray;
36583654
}
36593655

3660-
// If the given type is an object type and that type has a property by the given name,
3661-
// return the symbol for that property.Otherwise return undefined.
3656+
/** If the given type is an object type and that type has a property by the given name,
3657+
* return the symbol for that property. Otherwise return undefined. */
36623658
function getPropertyOfObjectType(type: Type, name: string): Symbol {
36633659
if (type.flags & TypeFlags.ObjectType) {
36643660
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//// [extendConstructSignatureInInterface.ts]
2+
interface C {
3+
new(x: number): C;
4+
}
5+
6+
var CStatic: C;
7+
class E extends CStatic {
8+
}
9+
10+
var e: E = new E(1);
11+
12+
13+
//// [extendConstructSignatureInInterface.js]
14+
var __extends = (this && this.__extends) || function (d, b) {
15+
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
16+
function __() { this.constructor = d; }
17+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
18+
};
19+
var CStatic;
20+
var E = (function (_super) {
21+
__extends(E, _super);
22+
function E() {
23+
_super.apply(this, arguments);
24+
}
25+
return E;
26+
})(CStatic);
27+
var e = new E(1);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
=== tests/cases/compiler/extendConstructSignatureInInterface.ts ===
2+
interface C {
3+
>C : Symbol(C, Decl(extendConstructSignatureInInterface.ts, 0, 0))
4+
5+
new(x: number): C;
6+
>x : Symbol(x, Decl(extendConstructSignatureInInterface.ts, 1, 8))
7+
>C : Symbol(C, Decl(extendConstructSignatureInInterface.ts, 0, 0))
8+
}
9+
10+
var CStatic: C;
11+
>CStatic : Symbol(CStatic, Decl(extendConstructSignatureInInterface.ts, 4, 3))
12+
>C : Symbol(C, Decl(extendConstructSignatureInInterface.ts, 0, 0))
13+
14+
class E extends CStatic {
15+
>E : Symbol(E, Decl(extendConstructSignatureInInterface.ts, 4, 15))
16+
>CStatic : Symbol(CStatic, Decl(extendConstructSignatureInInterface.ts, 4, 3))
17+
}
18+
19+
var e: E = new E(1);
20+
>e : Symbol(e, Decl(extendConstructSignatureInInterface.ts, 8, 3))
21+
>E : Symbol(E, Decl(extendConstructSignatureInInterface.ts, 4, 15))
22+
>E : Symbol(E, Decl(extendConstructSignatureInInterface.ts, 4, 15))
23+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
=== tests/cases/compiler/extendConstructSignatureInInterface.ts ===
2+
interface C {
3+
>C : C
4+
5+
new(x: number): C;
6+
>x : number
7+
>C : C
8+
}
9+
10+
var CStatic: C;
11+
>CStatic : C
12+
>C : C
13+
14+
class E extends CStatic {
15+
>E : E
16+
>CStatic : C
17+
}
18+
19+
var e: E = new E(1);
20+
>e : E
21+
>E : E
22+
>new E(1) : E
23+
>E : typeof E
24+
>1 : number
25+

tests/baselines/reference/recursiveBaseConstructorCreation3.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
tests/cases/compiler/recursiveBaseConstructorCreation3.ts(6,27): error TS2314: Generic type 'abc<T>' requires 1 type argument(s).
2-
tests/cases/compiler/recursiveBaseConstructorCreation3.ts(10,18): error TS2339: Property 'foo' does not exist on type 'xyz'.
2+
tests/cases/compiler/recursiveBaseConstructorCreation3.ts(9,11): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
33

44

55
==== tests/cases/compiler/recursiveBaseConstructorCreation3.ts (2 errors) ====
@@ -14,6 +14,6 @@ tests/cases/compiler/recursiveBaseConstructorCreation3.ts(10,18): error TS2339:
1414
}
1515

1616
var bar = new xyz(); // Error: Invalid 'new' expression.
17-
var r: xyz = bar.foo;
18-
~~~
19-
!!! error TS2339: Property 'foo' does not exist on type 'xyz'.
17+
~~~~~~~~~
18+
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
19+
var r: xyz = bar.foo;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
interface C {
2+
new(x: number): C;
3+
}
4+
5+
var CStatic: C;
6+
class E extends CStatic {
7+
}
8+
9+
var e: E = new E(1);

0 commit comments

Comments
 (0)