Merge pull request #5934 from Microsoft/inherit-construct-signature-from-extended-interface

Inherit construct signature from extended interface
This commit is contained in:
Nathan Shively-Sanders
2015-12-04 14:23:07 -08:00
6 changed files with 94 additions and 14 deletions

View File

@@ -2990,10 +2990,6 @@ namespace ts {
return type.resolvedBaseConstructorType;
}
function hasClassBaseType(type: InterfaceType): boolean {
return !!forEach(getBaseTypes(type), t => !!(t.symbol.flags & SymbolFlags.Class));
}
function getBaseTypes(type: InterfaceType): ObjectType[] {
const isClass = type.symbol.flags & SymbolFlags.Class;
const isInterface = type.symbol.flags & SymbolFlags.Interface;
@@ -3427,11 +3423,11 @@ namespace ts {
}
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
if (!hasClassBaseType(classType)) {
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
}
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
if (baseSignatures.length === 0) {
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
}
const baseTypeNode = getBaseTypeNodeOfClass(classType);
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
const typeArgCount = typeArguments ? typeArguments.length : 0;
@@ -3649,7 +3645,7 @@ namespace ts {
return <ResolvedType>type;
}
// Return properties of an object type or an empty array for other types
/** Return properties of an object type or an empty array for other types */
function getPropertiesOfObjectType(type: Type): Symbol[] {
if (type.flags & TypeFlags.ObjectType) {
return resolveStructuredTypeMembers(<ObjectType>type).properties;
@@ -3657,8 +3653,8 @@ namespace ts {
return emptyArray;
}
// If the given type is an object type and that type has a property by the given name,
// return the symbol for that property.Otherwise return undefined.
/** If the given type is an object type and that type has a property by the given name,
* return the symbol for that property. Otherwise return undefined. */
function getPropertyOfObjectType(type: Type, name: string): Symbol {
if (type.flags & TypeFlags.ObjectType) {
const resolved = resolveStructuredTypeMembers(<ObjectType>type);

View File

@@ -0,0 +1,27 @@
//// [extendConstructSignatureInInterface.ts]
interface C {
new(x: number): C;
}
var CStatic: C;
class E extends CStatic {
}
var e: E = new E(1);
//// [extendConstructSignatureInInterface.js]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var CStatic;
var E = (function (_super) {
__extends(E, _super);
function E() {
_super.apply(this, arguments);
}
return E;
})(CStatic);
var e = new E(1);

View File

@@ -0,0 +1,23 @@
=== tests/cases/compiler/extendConstructSignatureInInterface.ts ===
interface C {
>C : Symbol(C, Decl(extendConstructSignatureInInterface.ts, 0, 0))
new(x: number): C;
>x : Symbol(x, Decl(extendConstructSignatureInInterface.ts, 1, 8))
>C : Symbol(C, Decl(extendConstructSignatureInInterface.ts, 0, 0))
}
var CStatic: C;
>CStatic : Symbol(CStatic, Decl(extendConstructSignatureInInterface.ts, 4, 3))
>C : Symbol(C, Decl(extendConstructSignatureInInterface.ts, 0, 0))
class E extends CStatic {
>E : Symbol(E, Decl(extendConstructSignatureInInterface.ts, 4, 15))
>CStatic : Symbol(CStatic, Decl(extendConstructSignatureInInterface.ts, 4, 3))
}
var e: E = new E(1);
>e : Symbol(e, Decl(extendConstructSignatureInInterface.ts, 8, 3))
>E : Symbol(E, Decl(extendConstructSignatureInInterface.ts, 4, 15))
>E : Symbol(E, Decl(extendConstructSignatureInInterface.ts, 4, 15))

View File

@@ -0,0 +1,25 @@
=== tests/cases/compiler/extendConstructSignatureInInterface.ts ===
interface C {
>C : C
new(x: number): C;
>x : number
>C : C
}
var CStatic: C;
>CStatic : C
>C : C
class E extends CStatic {
>E : E
>CStatic : C
}
var e: E = new E(1);
>e : E
>E : E
>new E(1) : E
>E : typeof E
>1 : number

View File

@@ -1,5 +1,5 @@
tests/cases/compiler/recursiveBaseConstructorCreation3.ts(6,27): error TS2314: Generic type 'abc<T>' requires 1 type argument(s).
tests/cases/compiler/recursiveBaseConstructorCreation3.ts(10,18): error TS2339: Property 'foo' does not exist on type 'xyz'.
tests/cases/compiler/recursiveBaseConstructorCreation3.ts(9,11): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
==== tests/cases/compiler/recursiveBaseConstructorCreation3.ts (2 errors) ====
@@ -14,6 +14,6 @@ tests/cases/compiler/recursiveBaseConstructorCreation3.ts(10,18): error TS2339:
}
var bar = new xyz(); // Error: Invalid 'new' expression.
var r: xyz = bar.foo;
~~~
!!! error TS2339: Property 'foo' does not exist on type 'xyz'.
~~~~~~~~~
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
var r: xyz = bar.foo;

View File

@@ -0,0 +1,9 @@
interface C {
new(x: number): C;
}
var CStatic: C;
class E extends CStatic {
}
var e: E = new E(1);