support instantiate signature, it has type parameters.

This commit is contained in:
vvakame 2015-05-02 15:27:06 +09:00
parent 35d6e98e98
commit ab10d509f5
4 changed files with 380 additions and 35 deletions

View File

@ -5365,25 +5365,25 @@ module ts {
}
}
// Target type is type of constructor signiture
let constructorSignitures: Signature[];
let constructSignitures: Signature[];
if (rightType.flags & TypeFlags.Interface) {
constructorSignitures = (<InterfaceTypeWithDeclaredMembers>rightType).declaredConstructSignatures;
constructSignitures = (<InterfaceTypeWithDeclaredMembers>rightType).declaredConstructSignatures;
}
if (rightType.flags & TypeFlags.Anonymous) {
constructorSignitures = (<ResolvedType>rightType).constructSignatures;
constructSignitures = (<ResolvedType>rightType).constructSignatures;
}
if (constructorSignitures) {
let constructorType = getUnionType(map(constructorSignitures, constructorSignature => {
if (constructorSignature.typeParameters && constructorSignature.typeParameters.length !== 0) {
// TODO convert type parameters to any or empty object types. e.g. Sample<T> -> Sample<any> or Sample<{}>.
if (constructSignitures) {
let instanceType = getUnionType(map(constructSignitures, constructSignature => {
if (constructSignature.typeParameters && constructSignature.typeParameters.length !== 0) {
constructSignature = instantiateSignature(constructSignature, createTypeMapper(constructSignature.typeParameters, map(constructSignature.typeParameters, _ => anyType)), true)
}
return constructorSignature.resolvedReturnType;
return constructSignature.resolvedReturnType;
}));
// Pickup type from union types
if (type.flags & TypeFlags.Union) {
return getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, constructorType)));
return getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, instanceType)));
}
return constructorType;
return instanceType;
}
return type;
}

View File

@ -1,12 +1,16 @@
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(12,10): error TS2339: Property 'bar' does not exist on type 'A'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(32,10): error TS2339: Property 'foo' does not exist on type '{}'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(33,10): error TS2339: Property 'foo' does not exist on type '{}'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(34,10): error TS2339: Property 'bar' does not exist on type '{}'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(33,5): error TS2322: Type 'string' is not assignable to type 'number'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(34,10): error TS2339: Property 'bar' does not exist on type 'B<number>'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(63,10): error TS2339: Property 'bar2' does not exist on type 'C1'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(82,10): error TS2339: Property 'bar' does not exist on type 'D'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(109,10): error TS2339: Property 'bar2' does not exist on type 'E1'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(131,11): error TS2339: Property 'foo' does not exist on type 'string | F'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(132,11): error TS2339: Property 'bar' does not exist on type 'string | F'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(157,11): error TS2339: Property 'foo2' does not exist on type 'G1'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(179,11): error TS2339: Property 'bar' does not exist on type 'H'.
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts (6 errors) ====
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts (10 errors) ====
interface AConstructor {
new (): A;
}
@ -29,7 +33,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
obj2.bar;
}
// with generics
// a construct signature with generics
interface BConstructor {
new <T>(): B<T>;
}
@ -38,17 +42,15 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
}
declare var B: BConstructor;
var obj3: B<string> | A;
if (obj3 instanceof B) { // narrowed to B<string>.
obj3.foo = "str";
~~~
!!! error TS2339: Property 'foo' does not exist on type '{}'.
var obj3: B<number> | string;
if (obj3 instanceof B) { // narrowed to B<number>.
obj3.foo = 1;
~~~
!!! error TS2339: Property 'foo' does not exist on type '{}'.
obj3.foo = "str";
~~~~~~~~
!!! error TS2322: Type 'string' is not assignable to type 'number'.
obj3.bar = "str";
~~~
!!! error TS2339: Property 'bar' does not exist on type '{}'.
!!! error TS2339: Property 'bar' does not exist on type 'B<number>'.
}
var obj4: any;
@ -58,7 +60,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
obj4.bar = "str";
}
// has multiple constructor signature
// has multiple construct signature
interface CConstructor {
new (value: string): C1;
new (value: number): C2;
@ -108,4 +110,111 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
obj8.foo;
obj8.bar;
}
// a construct signature that returns a union type
interface EConstructor {
new (): E1 | E2;
}
interface E1 {
foo: string;
bar1: number;
}
interface E2 {
foo: string;
bar2: number;
}
declare var E: EConstructor;
var obj9: E1 | A;
if (obj9 instanceof E) { // narrowed to E1.
obj9.foo;
obj9.bar1;
obj9.bar2;
~~~~
!!! error TS2339: Property 'bar2' does not exist on type 'E1'.
}
var obj10: any;
if (obj10 instanceof E) { // can't type narrowing from any.
obj10.foo;
obj10.bar1;
obj10.bar2;
}
// a construct signature that returns any
interface FConstructor {
new (): any;
}
interface F {
foo: string;
bar: number;
}
declare var F: FConstructor;
var obj11: F | string;
if (obj11 instanceof F) { // can't type narrowing, construct signiture returns any.
obj11.foo;
~~~
!!! error TS2339: Property 'foo' does not exist on type 'string | F'.
obj11.bar;
~~~
!!! error TS2339: Property 'bar' does not exist on type 'string | F'.
}
var obj12: any;
if (obj12 instanceof F) { // can't type narrowing from any.
obj12.foo;
obj12.bar;
}
// a type with a prototype, it overrides the construct signiture
interface GConstructor {
prototype: G1; // high priority
new (): G2; // low priority
}
interface G1 {
foo1: number;
}
interface G2 {
foo2: boolean;
}
declare var G: GConstructor;
var obj13: G1 | G2;
if (obj13 instanceof G) { // narrowed to G1. G1 is return type of prototype property.
obj13.foo1;
obj13.foo2;
~~~~
!!! error TS2339: Property 'foo2' does not exist on type 'G1'.
}
var obj14: any;
if (obj14 instanceof G) { // can't type narrowing from any.
obj14.foo1;
obj14.foo2;
}
// a type with a prototype that has any type
interface HConstructor {
prototype: any; // high priority, but any type is ignored. interface has implicit `prototype: any`.
new (): H; // low priority
}
interface H {
foo: number;
}
declare var H: HConstructor;
var obj15: H | string;
if (obj15 instanceof H) { // narrowed to H.
obj15.foo;
obj15.bar;
~~~
!!! error TS2339: Property 'bar' does not exist on type 'H'.
}
var obj16: any;
if (obj16 instanceof H) { // can't type narrowing from any.
obj16.foo1;
obj16.foo2;
}

View File

@ -19,7 +19,7 @@ if (obj2 instanceof A) { // can't type narrowing from any.
obj2.bar;
}
// with generics
// a construct signature with generics
interface BConstructor {
new <T>(): B<T>;
}
@ -28,10 +28,10 @@ interface B<T> {
}
declare var B: BConstructor;
var obj3: B<string> | A;
if (obj3 instanceof B) { // narrowed to B<string>.
obj3.foo = "str";
var obj3: B<number> | string;
if (obj3 instanceof B) { // narrowed to B<number>.
obj3.foo = 1;
obj3.foo = "str";
obj3.bar = "str";
}
@ -42,7 +42,7 @@ if (obj4 instanceof B) { // can't type narrowing from any.
obj4.bar = "str";
}
// has multiple constructor signature
// has multiple construct signature
interface CConstructor {
new (value: string): C1;
new (value: number): C2;
@ -89,6 +89,103 @@ if (obj8 instanceof D) { // can't type narrowing from any.
obj8.bar;
}
// a construct signature that returns a union type
interface EConstructor {
new (): E1 | E2;
}
interface E1 {
foo: string;
bar1: number;
}
interface E2 {
foo: string;
bar2: number;
}
declare var E: EConstructor;
var obj9: E1 | A;
if (obj9 instanceof E) { // narrowed to E1.
obj9.foo;
obj9.bar1;
obj9.bar2;
}
var obj10: any;
if (obj10 instanceof E) { // can't type narrowing from any.
obj10.foo;
obj10.bar1;
obj10.bar2;
}
// a construct signature that returns any
interface FConstructor {
new (): any;
}
interface F {
foo: string;
bar: number;
}
declare var F: FConstructor;
var obj11: F | string;
if (obj11 instanceof F) { // can't type narrowing, construct signiture returns any.
obj11.foo;
obj11.bar;
}
var obj12: any;
if (obj12 instanceof F) { // can't type narrowing from any.
obj12.foo;
obj12.bar;
}
// a type with a prototype, it overrides the construct signiture
interface GConstructor {
prototype: G1; // high priority
new (): G2; // low priority
}
interface G1 {
foo1: number;
}
interface G2 {
foo2: boolean;
}
declare var G: GConstructor;
var obj13: G1 | G2;
if (obj13 instanceof G) { // narrowed to G1. G1 is return type of prototype property.
obj13.foo1;
obj13.foo2;
}
var obj14: any;
if (obj14 instanceof G) { // can't type narrowing from any.
obj14.foo1;
obj14.foo2;
}
// a type with a prototype that has any type
interface HConstructor {
prototype: any; // high priority, but any type is ignored. interface has implicit `prototype: any`.
new (): H; // low priority
}
interface H {
foo: number;
}
declare var H: HConstructor;
var obj15: H | string;
if (obj15 instanceof H) { // narrowed to H.
obj15.foo;
obj15.bar;
}
var obj16: any;
if (obj16 instanceof H) { // can't type narrowing from any.
obj16.foo1;
obj16.foo2;
}
//// [typeGuardsWithInstanceOfByConstructorSignature.js]
var obj1;
@ -103,8 +200,8 @@ if (obj2 instanceof A) {
}
var obj3;
if (obj3 instanceof B) {
obj3.foo = "str";
obj3.foo = 1;
obj3.foo = "str";
obj3.bar = "str";
}
var obj4;
@ -135,3 +232,45 @@ if (obj8 instanceof D) {
obj8.foo;
obj8.bar;
}
var obj9;
if (obj9 instanceof E) {
obj9.foo;
obj9.bar1;
obj9.bar2;
}
var obj10;
if (obj10 instanceof E) {
obj10.foo;
obj10.bar1;
obj10.bar2;
}
var obj11;
if (obj11 instanceof F) {
obj11.foo;
obj11.bar;
}
var obj12;
if (obj12 instanceof F) {
obj12.foo;
obj12.bar;
}
var obj13;
if (obj13 instanceof G) {
obj13.foo1;
obj13.foo2;
}
var obj14;
if (obj14 instanceof G) {
obj14.foo1;
obj14.foo2;
}
var obj15;
if (obj15 instanceof H) {
obj15.foo;
obj15.bar;
}
var obj16;
if (obj16 instanceof H) {
obj16.foo1;
obj16.foo2;
}

View File

@ -18,7 +18,7 @@ if (obj2 instanceof A) { // can't type narrowing from any.
obj2.bar;
}
// with generics
// a construct signature with generics
interface BConstructor {
new <T>(): B<T>;
}
@ -27,10 +27,10 @@ interface B<T> {
}
declare var B: BConstructor;
var obj3: B<string> | A;
if (obj3 instanceof B) { // narrowed to B<string>.
obj3.foo = "str";
var obj3: B<number> | string;
if (obj3 instanceof B) { // narrowed to B<number>.
obj3.foo = 1;
obj3.foo = "str";
obj3.bar = "str";
}
@ -41,7 +41,7 @@ if (obj4 instanceof B) { // can't type narrowing from any.
obj4.bar = "str";
}
// has multiple constructor signature
// has multiple construct signature
interface CConstructor {
new (value: string): C1;
new (value: number): C2;
@ -87,3 +87,100 @@ if (obj8 instanceof D) { // can't type narrowing from any.
obj8.foo;
obj8.bar;
}
// a construct signature that returns a union type
interface EConstructor {
new (): E1 | E2;
}
interface E1 {
foo: string;
bar1: number;
}
interface E2 {
foo: string;
bar2: number;
}
declare var E: EConstructor;
var obj9: E1 | A;
if (obj9 instanceof E) { // narrowed to E1.
obj9.foo;
obj9.bar1;
obj9.bar2;
}
var obj10: any;
if (obj10 instanceof E) { // can't type narrowing from any.
obj10.foo;
obj10.bar1;
obj10.bar2;
}
// a construct signature that returns any
interface FConstructor {
new (): any;
}
interface F {
foo: string;
bar: number;
}
declare var F: FConstructor;
var obj11: F | string;
if (obj11 instanceof F) { // can't type narrowing, construct signiture returns any.
obj11.foo;
obj11.bar;
}
var obj12: any;
if (obj12 instanceof F) { // can't type narrowing from any.
obj12.foo;
obj12.bar;
}
// a type with a prototype, it overrides the construct signiture
interface GConstructor {
prototype: G1; // high priority
new (): G2; // low priority
}
interface G1 {
foo1: number;
}
interface G2 {
foo2: boolean;
}
declare var G: GConstructor;
var obj13: G1 | G2;
if (obj13 instanceof G) { // narrowed to G1. G1 is return type of prototype property.
obj13.foo1;
obj13.foo2;
}
var obj14: any;
if (obj14 instanceof G) { // can't type narrowing from any.
obj14.foo1;
obj14.foo2;
}
// a type with a prototype that has any type
interface HConstructor {
prototype: any; // high priority, but any type is ignored. interface has implicit `prototype: any`.
new (): H; // low priority
}
interface H {
foo: number;
}
declare var H: HConstructor;
var obj15: H | string;
if (obj15 instanceof H) { // narrowed to H.
obj15.foo;
obj15.bar;
}
var obj16: any;
if (obj16 instanceof H) { // can't type narrowing from any.
obj16.foo1;
obj16.foo2;
}