Merge pull request #3798 from Microsoft/typeArgumentInferenceClassExpressions

Type argument inference for class expressions
This commit is contained in:
Jason Freeman 2015-07-09 14:56:49 -07:00
commit 9d6dc36e51
12 changed files with 185 additions and 1 deletions

View File

@ -5503,7 +5503,7 @@ namespace ts {
}
}
else if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
(target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral))) {
(target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
// If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
if (isInProcess(source, target)) {
return;

View File

@ -0,0 +1,22 @@
//// [typeArgumentInferenceWithClassExpression1.ts]
function foo<T>(x = class { static prop: T }): T {
return undefined;
}
foo(class { static prop = "hello" }).length;
//// [typeArgumentInferenceWithClassExpression1.js]
function foo(x) {
if (x === void 0) { x = (function () {
function class_1() {
}
return class_1;
})(); }
return undefined;
}
foo((function () {
function class_2() {
}
class_2.prop = "hello";
return class_2;
})()).length;

View File

@ -0,0 +1,19 @@
=== tests/cases/conformance/es6/classExpressions/typeArgumentInferenceWithClassExpression1.ts ===
function foo<T>(x = class { static prop: T }): T {
>foo : Symbol(foo, Decl(typeArgumentInferenceWithClassExpression1.ts, 0, 0))
>T : Symbol(T, Decl(typeArgumentInferenceWithClassExpression1.ts, 0, 13))
>x : Symbol(x, Decl(typeArgumentInferenceWithClassExpression1.ts, 0, 16))
>prop : Symbol((Anonymous class).prop, Decl(typeArgumentInferenceWithClassExpression1.ts, 0, 27))
>T : Symbol(T, Decl(typeArgumentInferenceWithClassExpression1.ts, 0, 13))
>T : Symbol(T, Decl(typeArgumentInferenceWithClassExpression1.ts, 0, 13))
return undefined;
>undefined : Symbol(undefined)
}
foo(class { static prop = "hello" }).length;
>foo(class { static prop = "hello" }).length : Symbol(String.length, Decl(lib.d.ts, 414, 19))
>foo : Symbol(foo, Decl(typeArgumentInferenceWithClassExpression1.ts, 0, 0))
>prop : Symbol((Anonymous class).prop, Decl(typeArgumentInferenceWithClassExpression1.ts, 4, 11))
>length : Symbol(String.length, Decl(lib.d.ts, 414, 19))

View File

@ -0,0 +1,23 @@
=== tests/cases/conformance/es6/classExpressions/typeArgumentInferenceWithClassExpression1.ts ===
function foo<T>(x = class { static prop: T }): T {
>foo : <T>(x?: typeof (Anonymous class)) => T
>T : T
>x : typeof (Anonymous class)
>class { static prop: T } : typeof (Anonymous class)
>prop : T
>T : T
>T : T
return undefined;
>undefined : undefined
}
foo(class { static prop = "hello" }).length;
>foo(class { static prop = "hello" }).length : number
>foo(class { static prop = "hello" }) : string
>foo : <T>(x?: typeof (Anonymous class)) => T
>class { static prop = "hello" } : typeof (Anonymous class)
>prop : string
>"hello" : string
>length : number

View File

@ -0,0 +1,16 @@
tests/cases/conformance/es6/classExpressions/typeArgumentInferenceWithClassExpression2.ts(6,5): error TS2345: Argument of type 'typeof (Anonymous class)' is not assignable to parameter of type 'typeof (Anonymous class)'.
Type '(Anonymous class)' is not assignable to type 'foo<{}>.'.
Property 'prop' is missing in type '(Anonymous class)'.
==== tests/cases/conformance/es6/classExpressions/typeArgumentInferenceWithClassExpression2.ts (1 errors) ====
function foo<T>(x = class { prop: T }): T {
return undefined;
}
// Should not infer string because it is a static property
foo(class { static prop = "hello" }).length;
~~~~~
!!! error TS2345: Argument of type 'typeof (Anonymous class)' is not assignable to parameter of type 'typeof (Anonymous class)'.
!!! error TS2345: Type '(Anonymous class)' is not assignable to type 'foo<{}>.'.
!!! error TS2345: Property 'prop' is missing in type '(Anonymous class)'.

View File

@ -0,0 +1,24 @@
//// [typeArgumentInferenceWithClassExpression2.ts]
function foo<T>(x = class { prop: T }): T {
return undefined;
}
// Should not infer string because it is a static property
foo(class { static prop = "hello" }).length;
//// [typeArgumentInferenceWithClassExpression2.js]
function foo(x) {
if (x === void 0) { x = (function () {
function class_1() {
}
return class_1;
})(); }
return undefined;
}
// Should not infer string because it is a static property
foo((function () {
function class_2() {
}
class_2.prop = "hello";
return class_2;
})()).length;

View File

@ -0,0 +1,22 @@
//// [typeArgumentInferenceWithClassExpression3.ts]
function foo<T>(x = class { prop: T }): T {
return undefined;
}
foo(class { prop = "hello" }).length;
//// [typeArgumentInferenceWithClassExpression3.js]
function foo(x) {
if (x === void 0) { x = (function () {
function class_1() {
}
return class_1;
})(); }
return undefined;
}
foo((function () {
function class_2() {
this.prop = "hello";
}
return class_2;
})()).length;

View File

@ -0,0 +1,19 @@
=== tests/cases/conformance/es6/classExpressions/typeArgumentInferenceWithClassExpression3.ts ===
function foo<T>(x = class { prop: T }): T {
>foo : Symbol(foo, Decl(typeArgumentInferenceWithClassExpression3.ts, 0, 0))
>T : Symbol(T, Decl(typeArgumentInferenceWithClassExpression3.ts, 0, 13))
>x : Symbol(x, Decl(typeArgumentInferenceWithClassExpression3.ts, 0, 16))
>prop : Symbol((Anonymous class).prop, Decl(typeArgumentInferenceWithClassExpression3.ts, 0, 27))
>T : Symbol(T, Decl(typeArgumentInferenceWithClassExpression3.ts, 0, 13))
>T : Symbol(T, Decl(typeArgumentInferenceWithClassExpression3.ts, 0, 13))
return undefined;
>undefined : Symbol(undefined)
}
foo(class { prop = "hello" }).length;
>foo(class { prop = "hello" }).length : Symbol(String.length, Decl(lib.d.ts, 414, 19))
>foo : Symbol(foo, Decl(typeArgumentInferenceWithClassExpression3.ts, 0, 0))
>prop : Symbol((Anonymous class).prop, Decl(typeArgumentInferenceWithClassExpression3.ts, 4, 11))
>length : Symbol(String.length, Decl(lib.d.ts, 414, 19))

View File

@ -0,0 +1,23 @@
=== tests/cases/conformance/es6/classExpressions/typeArgumentInferenceWithClassExpression3.ts ===
function foo<T>(x = class { prop: T }): T {
>foo : <T>(x?: typeof (Anonymous class)) => T
>T : T
>x : typeof (Anonymous class)
>class { prop: T } : typeof (Anonymous class)
>prop : T
>T : T
>T : T
return undefined;
>undefined : undefined
}
foo(class { prop = "hello" }).length;
>foo(class { prop = "hello" }).length : number
>foo(class { prop = "hello" }) : string
>foo : <T>(x?: typeof (Anonymous class)) => T
>class { prop = "hello" } : typeof (Anonymous class)
>prop : string
>"hello" : string
>length : number

View File

@ -0,0 +1,5 @@
function foo<T>(x = class { static prop: T }): T {
return undefined;
}
foo(class { static prop = "hello" }).length;

View File

@ -0,0 +1,6 @@
function foo<T>(x = class { prop: T }): T {
return undefined;
}
// Should not infer string because it is a static property
foo(class { static prop = "hello" }).length;

View File

@ -0,0 +1,5 @@
function foo<T>(x = class { prop: T }): T {
return undefined;
}
foo(class { prop = "hello" }).length;