From 1085e39b9a489f82b65c8dfff0e303abdf9e27d8 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 2 Jul 2015 15:20:57 -0700 Subject: [PATCH 1/3] Always take the apparent type when you retrieve a contextual type --- src/compiler/checker.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d3d8ac1bc1b..65545efbcd2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6442,6 +6442,11 @@ namespace ts { // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily // be "pushed" onto a node using the contextualType property. function getContextualType(node: Expression): Type { + let type = getContextualTypeWorker(node); + return type && getApparentType(type); + } + + function getContextualTypeWorker(node: Expression): Type { if (isInsideWithStatementBody(node)) { // We cannot answer semantic questions within a with block, do not proceed any further return undefined; From 98de6117f1cab5861bece38ece96b7e3b56abb5a Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 2 Jul 2015 15:21:09 -0700 Subject: [PATCH 2/3] Accept baselines --- ...ndAdditionAssignmentLHSCanBeAssigned.types | 2 +- ...ualTypeWithUnionTypeCallSignatures.symbols | 2 ++ ...xtualTypeWithUnionTypeCallSignatures.types | 12 ++++---- .../functionConstraintSatisfaction3.types | 28 +++++++++---------- .../genericCallWithTupleType.errors.txt | 8 +++--- .../reference/noErrorsInCallback.errors.txt | 8 +++--- .../typeParameterFixingWithConstraints.types | 10 +++---- ...wrappedAndRecursiveConstraints4.errors.txt | 4 +-- 8 files changed, 38 insertions(+), 36 deletions(-) diff --git a/tests/baselines/reference/compoundAdditionAssignmentLHSCanBeAssigned.types b/tests/baselines/reference/compoundAdditionAssignmentLHSCanBeAssigned.types index e40422450b4..92835611c6d 100644 --- a/tests/baselines/reference/compoundAdditionAssignmentLHSCanBeAssigned.types +++ b/tests/baselines/reference/compoundAdditionAssignmentLHSCanBeAssigned.types @@ -98,7 +98,7 @@ x2 += E.a; x2 += {}; >x2 += {} : string >x2 : string ->{} : {} +>{} : { [x: number]: undefined; } x2 += null; >x2 += null : string diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.symbols b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.symbols index 172336603ab..3e23a7812f5 100644 --- a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.symbols +++ b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.symbols @@ -82,5 +82,7 @@ var x4: IWithCallSignatures | IWithCallSignatures4 = a => /*here a should be any >IWithCallSignatures : Symbol(IWithCallSignatures, Decl(contextualTypeWithUnionTypeCallSignatures.ts, 9, 1)) >IWithCallSignatures4 : Symbol(IWithCallSignatures4, Decl(contextualTypeWithUnionTypeCallSignatures.ts, 18, 1)) >a : Symbol(a, Decl(contextualTypeWithUnionTypeCallSignatures.ts, 35, 52)) +>a.toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) >a : Symbol(a, Decl(contextualTypeWithUnionTypeCallSignatures.ts, 35, 52)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types index 02dfecf5c08..8e1915d4754 100644 --- a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types +++ b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types @@ -90,10 +90,10 @@ var x4: IWithCallSignatures | IWithCallSignatures4 = a => /*here a should be any >x4 : IWithCallSignatures | IWithCallSignatures4 >IWithCallSignatures : IWithCallSignatures >IWithCallSignatures4 : IWithCallSignatures4 ->a => /*here a should be any*/ a.toString() : (a: any) => any ->a : any ->a.toString() : any ->a.toString : any ->a : any ->toString : any +>a => /*here a should be any*/ a.toString() : (a: number) => string +>a : number +>a.toString() : string +>a.toString : (radix?: number) => string +>a : number +>toString : (radix?: number) => string diff --git a/tests/baselines/reference/functionConstraintSatisfaction3.types b/tests/baselines/reference/functionConstraintSatisfaction3.types index 04963c36519..c58e62f6995 100644 --- a/tests/baselines/reference/functionConstraintSatisfaction3.types +++ b/tests/baselines/reference/functionConstraintSatisfaction3.types @@ -37,12 +37,12 @@ var c: { (): string; (x): string }; >x : any var r1 = foo((x) => x); ->r1 : (x: any) => any ->foo((x) => x) : (x: any) => any +>r1 : (x: string) => string +>foo((x) => x) : (x: string) => string >foo : string>(x: T) => T ->(x) => x : (x: any) => any ->x : any ->x : any +>(x) => x : (x: string) => string +>x : string +>x : string var r2 = foo((x: string) => x); >r2 : (x: string) => string @@ -53,12 +53,12 @@ var r2 = foo((x: string) => x); >x : string var r3 = foo(function (x) { return x }); ->r3 : (x: any) => any ->foo(function (x) { return x }) : (x: any) => any +>r3 : (x: string) => string +>foo(function (x) { return x }) : (x: string) => string >foo : string>(x: T) => T ->function (x) { return x } : (x: any) => any ->x : any ->x : any +>function (x) { return x } : (x: string) => string +>x : string +>x : string var r4 = foo(function (x: string) { return x }); >r4 : (x: string) => string @@ -130,8 +130,8 @@ var c2: { (x: T): T; (x: T, y: T): T }; >T : T var r9 = foo(function (x: U) { return x; }); ->r9 : (x: U) => U ->foo(function (x: U) { return x; }) : (x: U) => U +>r9 : (x: string) => string +>foo(function (x: U) { return x; }) : (x: string) => string >foo : string>(x: T) => T >function (x: U) { return x; } : (x: U) => U >U : U @@ -140,8 +140,8 @@ var r9 = foo(function (x: U) { return x; }); >x : U var r10 = foo((x: U) => x); ->r10 : (x: U) => U ->foo((x: U) => x) : (x: U) => U +>r10 : (x: string) => string +>foo((x: U) => x) : (x: string) => string >foo : string>(x: T) => T >(x: U) => x : (x: U) => U >U : U diff --git a/tests/baselines/reference/genericCallWithTupleType.errors.txt b/tests/baselines/reference/genericCallWithTupleType.errors.txt index bcf580320e5..d03f8d5e68a 100644 --- a/tests/baselines/reference/genericCallWithTupleType.errors.txt +++ b/tests/baselines/reference/genericCallWithTupleType.errors.txt @@ -9,9 +9,9 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTup tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(22,1): error TS2322: Type '[number, string]' is not assignable to type '[string, number]'. Types of property '0' are incompatible. Type 'number' is not assignable to type 'string'. -tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(23,1): error TS2322: Type '[{}, {}]' is not assignable to type '[string, number]'. +tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(23,1): error TS2322: Type '[{ [x: number]: undefined; }, {}]' is not assignable to type '[string, number]'. Types of property '0' are incompatible. - Type '{}' is not assignable to type 'string'. + Type '{ [x: number]: undefined; }' is not assignable to type 'string'. tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(24,1): error TS2322: Type '[{}]' is not assignable to type '[{}, {}]'. Property '1' is missing in type '[{}]'. @@ -55,9 +55,9 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTup !!! error TS2322: Type 'number' is not assignable to type 'string'. i1.tuple1 = [{}, {}]; ~~~~~~~~~ -!!! error TS2322: Type '[{}, {}]' is not assignable to type '[string, number]'. +!!! error TS2322: Type '[{ [x: number]: undefined; }, {}]' is not assignable to type '[string, number]'. !!! error TS2322: Types of property '0' are incompatible. -!!! error TS2322: Type '{}' is not assignable to type 'string'. +!!! error TS2322: Type '{ [x: number]: undefined; }' is not assignable to type 'string'. i2.tuple1 = [{}]; ~~~~~~~~~ !!! error TS2322: Type '[{}]' is not assignable to type '[{}, {}]'. diff --git a/tests/baselines/reference/noErrorsInCallback.errors.txt b/tests/baselines/reference/noErrorsInCallback.errors.txt index f0bfe00199e..90fdbbd77a5 100644 --- a/tests/baselines/reference/noErrorsInCallback.errors.txt +++ b/tests/baselines/reference/noErrorsInCallback.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/noErrorsInCallback.ts(4,19): error TS2345: Argument of type '{}' is not assignable to parameter of type 'string'. -tests/cases/compiler/noErrorsInCallback.ts(6,23): error TS2345: Argument of type '{}' is not assignable to parameter of type 'string'. +tests/cases/compiler/noErrorsInCallback.ts(4,19): error TS2345: Argument of type '{ [x: number]: undefined; }' is not assignable to parameter of type 'string'. +tests/cases/compiler/noErrorsInCallback.ts(6,23): error TS2345: Argument of type '{ [x: number]: undefined; }' is not assignable to parameter of type 'string'. ==== tests/cases/compiler/noErrorsInCallback.ts (2 errors) ==== @@ -8,10 +8,10 @@ tests/cases/compiler/noErrorsInCallback.ts(6,23): error TS2345: Argument of type } var one = new Bar({}); // Error ~~ -!!! error TS2345: Argument of type '{}' is not assignable to parameter of type 'string'. +!!! error TS2345: Argument of type '{ [x: number]: undefined; }' is not assignable to parameter of type 'string'. [].forEach(() => { var two = new Bar({}); // No error? ~~ -!!! error TS2345: Argument of type '{}' is not assignable to parameter of type 'string'. +!!! error TS2345: Argument of type '{ [x: number]: undefined; }' is not assignable to parameter of type 'string'. }); \ No newline at end of file diff --git a/tests/baselines/reference/typeParameterFixingWithConstraints.types b/tests/baselines/reference/typeParameterFixingWithConstraints.types index 64876952852..22d294f9d2e 100644 --- a/tests/baselines/reference/typeParameterFixingWithConstraints.types +++ b/tests/baselines/reference/typeParameterFixingWithConstraints.types @@ -31,17 +31,17 @@ var foo: IFoo; >IFoo : IFoo foo.foo({ bar: null }, bar => null, bar => null); ->foo.foo({ bar: null }, bar => null, bar => null) : IBar +>foo.foo({ bar: null }, bar => null, bar => null) : { [x: string]: any; bar: any; } >foo.foo : (bar: TBar, bar1: (bar: TBar) => TBar, bar2: (bar: TBar) => TBar) => TBar >foo : IFoo >foo : (bar: TBar, bar1: (bar: TBar) => TBar, bar2: (bar: TBar) => TBar) => TBar >{ bar: null } : { [x: string]: null; bar: null; } >bar : null >null : null ->bar => null : (bar: IBar) => any ->bar : IBar +>bar => null : (bar: { [x: string]: any; bar: any; }) => any +>bar : { [x: string]: any; bar: any; } >null : null ->bar => null : (bar: IBar) => any ->bar : IBar +>bar => null : (bar: { [x: string]: any; bar: any; }) => any +>bar : { [x: string]: any; bar: any; } >null : null diff --git a/tests/baselines/reference/wrappedAndRecursiveConstraints4.errors.txt b/tests/baselines/reference/wrappedAndRecursiveConstraints4.errors.txt index 47e8e6ff4f2..60602351b46 100644 --- a/tests/baselines/reference/wrappedAndRecursiveConstraints4.errors.txt +++ b/tests/baselines/reference/wrappedAndRecursiveConstraints4.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/typeParameters/typeArgumentLists/wrappedAndRecursiveConstraints4.ts(13,12): error TS2345: Argument of type '{ length: number; charAt: (x: number) => void; }' is not assignable to parameter of type 'string'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/wrappedAndRecursiveConstraints4.ts(13,12): error TS2345: Argument of type '{ [x: number]: undefined; length: number; charAt: (x: number) => void; }' is not assignable to parameter of type 'string'. ==== tests/cases/conformance/types/typeParameters/typeArgumentLists/wrappedAndRecursiveConstraints4.ts (1 errors) ==== @@ -16,4 +16,4 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/wrappedAndRecursi var r = c.foo(''); var r2 = r({ length: 3, charAt: (x: number) => { '' } }); // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '{ length: number; charAt: (x: number) => void; }' is not assignable to parameter of type 'string'. \ No newline at end of file +!!! error TS2345: Argument of type '{ [x: number]: undefined; length: number; charAt: (x: number) => void; }' is not assignable to parameter of type 'string'. \ No newline at end of file From 652995181e41ca5b4347fdbd8f5377c2b944da6f Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 2 Jul 2015 15:21:43 -0700 Subject: [PATCH 3/3] Add tests for inferential typing --- .../inferentialTypingUsingApparentType1.js | 12 +++ ...nferentialTypingUsingApparentType1.symbols | 20 +++++ .../inferentialTypingUsingApparentType1.types | 22 ++++++ .../inferentialTypingUsingApparentType2.js | 12 +++ ...nferentialTypingUsingApparentType2.symbols | 22 ++++++ .../inferentialTypingUsingApparentType2.types | 24 ++++++ .../inferentialTypingUsingApparentType3.js | 56 ++++++++++++++ ...nferentialTypingUsingApparentType3.symbols | 69 +++++++++++++++++ .../inferentialTypingUsingApparentType3.types | 75 +++++++++++++++++++ .../inferentialTypingUsingApparentType1.ts | 5 ++ .../inferentialTypingUsingApparentType2.ts | 5 ++ .../inferentialTypingUsingApparentType3.ts | 26 +++++++ 12 files changed, 348 insertions(+) create mode 100644 tests/baselines/reference/inferentialTypingUsingApparentType1.js create mode 100644 tests/baselines/reference/inferentialTypingUsingApparentType1.symbols create mode 100644 tests/baselines/reference/inferentialTypingUsingApparentType1.types create mode 100644 tests/baselines/reference/inferentialTypingUsingApparentType2.js create mode 100644 tests/baselines/reference/inferentialTypingUsingApparentType2.symbols create mode 100644 tests/baselines/reference/inferentialTypingUsingApparentType2.types create mode 100644 tests/baselines/reference/inferentialTypingUsingApparentType3.js create mode 100644 tests/baselines/reference/inferentialTypingUsingApparentType3.symbols create mode 100644 tests/baselines/reference/inferentialTypingUsingApparentType3.types create mode 100644 tests/cases/compiler/inferentialTypingUsingApparentType1.ts create mode 100644 tests/cases/compiler/inferentialTypingUsingApparentType2.ts create mode 100644 tests/cases/compiler/inferentialTypingUsingApparentType3.ts diff --git a/tests/baselines/reference/inferentialTypingUsingApparentType1.js b/tests/baselines/reference/inferentialTypingUsingApparentType1.js new file mode 100644 index 00000000000..02161a98695 --- /dev/null +++ b/tests/baselines/reference/inferentialTypingUsingApparentType1.js @@ -0,0 +1,12 @@ +//// [inferentialTypingUsingApparentType1.ts] +function foo number>(x: T): T { + return undefined; +} + +foo(x => x.length); + +//// [inferentialTypingUsingApparentType1.js] +function foo(x) { + return undefined; +} +foo(function (x) { return x.length; }); diff --git a/tests/baselines/reference/inferentialTypingUsingApparentType1.symbols b/tests/baselines/reference/inferentialTypingUsingApparentType1.symbols new file mode 100644 index 00000000000..4babc614183 --- /dev/null +++ b/tests/baselines/reference/inferentialTypingUsingApparentType1.symbols @@ -0,0 +1,20 @@ +=== tests/cases/compiler/inferentialTypingUsingApparentType1.ts === +function foo number>(x: T): T { +>foo : Symbol(foo, Decl(inferentialTypingUsingApparentType1.ts, 0, 0)) +>T : Symbol(T, Decl(inferentialTypingUsingApparentType1.ts, 0, 13)) +>p : Symbol(p, Decl(inferentialTypingUsingApparentType1.ts, 0, 24)) +>x : Symbol(x, Decl(inferentialTypingUsingApparentType1.ts, 0, 46)) +>T : Symbol(T, Decl(inferentialTypingUsingApparentType1.ts, 0, 13)) +>T : Symbol(T, Decl(inferentialTypingUsingApparentType1.ts, 0, 13)) + + return undefined; +>undefined : Symbol(undefined) +} + +foo(x => x.length); +>foo : Symbol(foo, Decl(inferentialTypingUsingApparentType1.ts, 0, 0)) +>x : Symbol(x, Decl(inferentialTypingUsingApparentType1.ts, 4, 4)) +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(inferentialTypingUsingApparentType1.ts, 4, 4)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) + diff --git a/tests/baselines/reference/inferentialTypingUsingApparentType1.types b/tests/baselines/reference/inferentialTypingUsingApparentType1.types new file mode 100644 index 00000000000..b56f3670ddc --- /dev/null +++ b/tests/baselines/reference/inferentialTypingUsingApparentType1.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/inferentialTypingUsingApparentType1.ts === +function foo number>(x: T): T { +>foo : number>(x: T) => T +>T : T +>p : string +>x : T +>T : T +>T : T + + return undefined; +>undefined : undefined +} + +foo(x => x.length); +>foo(x => x.length) : (x: string) => number +>foo : number>(x: T) => T +>x => x.length : (x: string) => number +>x : string +>x.length : number +>x : string +>length : number + diff --git a/tests/baselines/reference/inferentialTypingUsingApparentType2.js b/tests/baselines/reference/inferentialTypingUsingApparentType2.js new file mode 100644 index 00000000000..7cb7e49cd62 --- /dev/null +++ b/tests/baselines/reference/inferentialTypingUsingApparentType2.js @@ -0,0 +1,12 @@ +//// [inferentialTypingUsingApparentType2.ts] +function foo(x: T): T { + return undefined; +} + +foo({ m(x) { return x.length } }); + +//// [inferentialTypingUsingApparentType2.js] +function foo(x) { + return undefined; +} +foo({ m: function (x) { return x.length; } }); diff --git a/tests/baselines/reference/inferentialTypingUsingApparentType2.symbols b/tests/baselines/reference/inferentialTypingUsingApparentType2.symbols new file mode 100644 index 00000000000..3c47eb4c697 --- /dev/null +++ b/tests/baselines/reference/inferentialTypingUsingApparentType2.symbols @@ -0,0 +1,22 @@ +=== tests/cases/compiler/inferentialTypingUsingApparentType2.ts === +function foo(x: T): T { +>foo : Symbol(foo, Decl(inferentialTypingUsingApparentType2.ts, 0, 0)) +>T : Symbol(T, Decl(inferentialTypingUsingApparentType2.ts, 0, 13)) +>m : Symbol(m, Decl(inferentialTypingUsingApparentType2.ts, 0, 24)) +>p : Symbol(p, Decl(inferentialTypingUsingApparentType2.ts, 0, 27)) +>x : Symbol(x, Decl(inferentialTypingUsingApparentType2.ts, 0, 49)) +>T : Symbol(T, Decl(inferentialTypingUsingApparentType2.ts, 0, 13)) +>T : Symbol(T, Decl(inferentialTypingUsingApparentType2.ts, 0, 13)) + + return undefined; +>undefined : Symbol(undefined) +} + +foo({ m(x) { return x.length } }); +>foo : Symbol(foo, Decl(inferentialTypingUsingApparentType2.ts, 0, 0)) +>m : Symbol(m, Decl(inferentialTypingUsingApparentType2.ts, 4, 5)) +>x : Symbol(x, Decl(inferentialTypingUsingApparentType2.ts, 4, 8)) +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(inferentialTypingUsingApparentType2.ts, 4, 8)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) + diff --git a/tests/baselines/reference/inferentialTypingUsingApparentType2.types b/tests/baselines/reference/inferentialTypingUsingApparentType2.types new file mode 100644 index 00000000000..597f5885f5a --- /dev/null +++ b/tests/baselines/reference/inferentialTypingUsingApparentType2.types @@ -0,0 +1,24 @@ +=== tests/cases/compiler/inferentialTypingUsingApparentType2.ts === +function foo(x: T): T { +>foo : (x: T) => T +>T : T +>m : (p: string) => number +>p : string +>x : T +>T : T +>T : T + + return undefined; +>undefined : undefined +} + +foo({ m(x) { return x.length } }); +>foo({ m(x) { return x.length } }) : { } +>foo : (x: T) => T +>{ m(x) { return x.length } } : { m(x: string): number; } +>m : (x: string) => number +>x : string +>x.length : number +>x : string +>length : number + diff --git a/tests/baselines/reference/inferentialTypingUsingApparentType3.js b/tests/baselines/reference/inferentialTypingUsingApparentType3.js new file mode 100644 index 00000000000..819ca05098d --- /dev/null +++ b/tests/baselines/reference/inferentialTypingUsingApparentType3.js @@ -0,0 +1,56 @@ +//// [inferentialTypingUsingApparentType3.ts] +interface Field { + clean(input: T): T +} + +class CharField implements Field { + clean(input: string) { + return "Yup"; + } +} + +class NumberField implements Field { + clean(input: number) { + return 123; + } +} + +class ObjectField }> { + constructor(public fields: T) { } +} + +var person = new ObjectField({ + id: new NumberField(), + name: new CharField() +}); + +person.fields.id; + +//// [inferentialTypingUsingApparentType3.js] +var CharField = (function () { + function CharField() { + } + CharField.prototype.clean = function (input) { + return "Yup"; + }; + return CharField; +})(); +var NumberField = (function () { + function NumberField() { + } + NumberField.prototype.clean = function (input) { + return 123; + }; + return NumberField; +})(); +var ObjectField = (function () { + function ObjectField(fields) { + this.fields = fields; + } + return ObjectField; +})(); +var person = new ObjectField({ + id: new NumberField(), + name: new CharField() +}); +person.fields.id; diff --git a/tests/baselines/reference/inferentialTypingUsingApparentType3.symbols b/tests/baselines/reference/inferentialTypingUsingApparentType3.symbols new file mode 100644 index 00000000000..ac3058e8649 --- /dev/null +++ b/tests/baselines/reference/inferentialTypingUsingApparentType3.symbols @@ -0,0 +1,69 @@ +=== tests/cases/compiler/inferentialTypingUsingApparentType3.ts === +interface Field { +>Field : Symbol(Field, Decl(inferentialTypingUsingApparentType3.ts, 0, 0)) +>T : Symbol(T, Decl(inferentialTypingUsingApparentType3.ts, 0, 16)) + + clean(input: T): T +>clean : Symbol(clean, Decl(inferentialTypingUsingApparentType3.ts, 0, 20)) +>input : Symbol(input, Decl(inferentialTypingUsingApparentType3.ts, 1, 10)) +>T : Symbol(T, Decl(inferentialTypingUsingApparentType3.ts, 0, 16)) +>T : Symbol(T, Decl(inferentialTypingUsingApparentType3.ts, 0, 16)) +} + +class CharField implements Field { +>CharField : Symbol(CharField, Decl(inferentialTypingUsingApparentType3.ts, 2, 1)) +>Field : Symbol(Field, Decl(inferentialTypingUsingApparentType3.ts, 0, 0)) + + clean(input: string) { +>clean : Symbol(clean, Decl(inferentialTypingUsingApparentType3.ts, 4, 42)) +>input : Symbol(input, Decl(inferentialTypingUsingApparentType3.ts, 5, 10)) + + return "Yup"; + } +} + +class NumberField implements Field { +>NumberField : Symbol(NumberField, Decl(inferentialTypingUsingApparentType3.ts, 8, 1)) +>Field : Symbol(Field, Decl(inferentialTypingUsingApparentType3.ts, 0, 0)) + + clean(input: number) { +>clean : Symbol(clean, Decl(inferentialTypingUsingApparentType3.ts, 10, 44)) +>input : Symbol(input, Decl(inferentialTypingUsingApparentType3.ts, 11, 10)) + + return 123; + } +} + +class ObjectField }> { +>ObjectField : Symbol(ObjectField, Decl(inferentialTypingUsingApparentType3.ts, 14, 1)) +>A : Symbol(A, Decl(inferentialTypingUsingApparentType3.ts, 16, 18)) +>T : Symbol(T, Decl(inferentialTypingUsingApparentType3.ts, 16, 20)) +>name : Symbol(name, Decl(inferentialTypingUsingApparentType3.ts, 16, 34)) +>Field : Symbol(Field, Decl(inferentialTypingUsingApparentType3.ts, 0, 0)) + + constructor(public fields: T) { } +>fields : Symbol(fields, Decl(inferentialTypingUsingApparentType3.ts, 17, 16)) +>T : Symbol(T, Decl(inferentialTypingUsingApparentType3.ts, 16, 20)) +} + +var person = new ObjectField({ +>person : Symbol(person, Decl(inferentialTypingUsingApparentType3.ts, 20, 3)) +>ObjectField : Symbol(ObjectField, Decl(inferentialTypingUsingApparentType3.ts, 14, 1)) + + id: new NumberField(), +>id : Symbol(id, Decl(inferentialTypingUsingApparentType3.ts, 20, 30)) +>NumberField : Symbol(NumberField, Decl(inferentialTypingUsingApparentType3.ts, 8, 1)) + + name: new CharField() +>name : Symbol(name, Decl(inferentialTypingUsingApparentType3.ts, 21, 26)) +>CharField : Symbol(CharField, Decl(inferentialTypingUsingApparentType3.ts, 2, 1)) + +}); + +person.fields.id; +>person.fields.id : Symbol(id, Decl(inferentialTypingUsingApparentType3.ts, 20, 30)) +>person.fields : Symbol(ObjectField.fields, Decl(inferentialTypingUsingApparentType3.ts, 17, 16)) +>person : Symbol(person, Decl(inferentialTypingUsingApparentType3.ts, 20, 3)) +>fields : Symbol(ObjectField.fields, Decl(inferentialTypingUsingApparentType3.ts, 17, 16)) +>id : Symbol(id, Decl(inferentialTypingUsingApparentType3.ts, 20, 30)) + diff --git a/tests/baselines/reference/inferentialTypingUsingApparentType3.types b/tests/baselines/reference/inferentialTypingUsingApparentType3.types new file mode 100644 index 00000000000..7d0da8f4b06 --- /dev/null +++ b/tests/baselines/reference/inferentialTypingUsingApparentType3.types @@ -0,0 +1,75 @@ +=== tests/cases/compiler/inferentialTypingUsingApparentType3.ts === +interface Field { +>Field : Field +>T : T + + clean(input: T): T +>clean : (input: T) => T +>input : T +>T : T +>T : T +} + +class CharField implements Field { +>CharField : CharField +>Field : Field + + clean(input: string) { +>clean : (input: string) => string +>input : string + + return "Yup"; +>"Yup" : string + } +} + +class NumberField implements Field { +>NumberField : NumberField +>Field : Field + + clean(input: number) { +>clean : (input: number) => number +>input : number + + return 123; +>123 : number + } +} + +class ObjectField }> { +>ObjectField : ObjectField +>A : A +>T : T +>name : string +>Field : Field + + constructor(public fields: T) { } +>fields : T +>T : T +} + +var person = new ObjectField({ +>person : ObjectField<{}, { [x: string]: CharField | NumberField; id: NumberField; name: CharField; }> +>new ObjectField({ id: new NumberField(), name: new CharField()}) : ObjectField<{}, { [x: string]: CharField | NumberField; id: NumberField; name: CharField; }> +>ObjectField : typeof ObjectField +>{ id: new NumberField(), name: new CharField()} : { [x: string]: CharField | NumberField; id: NumberField; name: CharField; } + + id: new NumberField(), +>id : NumberField +>new NumberField() : NumberField +>NumberField : typeof NumberField + + name: new CharField() +>name : CharField +>new CharField() : CharField +>CharField : typeof CharField + +}); + +person.fields.id; +>person.fields.id : NumberField +>person.fields : { [x: string]: CharField | NumberField; id: NumberField; name: CharField; } +>person : ObjectField<{}, { [x: string]: CharField | NumberField; id: NumberField; name: CharField; }> +>fields : { [x: string]: CharField | NumberField; id: NumberField; name: CharField; } +>id : NumberField + diff --git a/tests/cases/compiler/inferentialTypingUsingApparentType1.ts b/tests/cases/compiler/inferentialTypingUsingApparentType1.ts new file mode 100644 index 00000000000..98920cf693f --- /dev/null +++ b/tests/cases/compiler/inferentialTypingUsingApparentType1.ts @@ -0,0 +1,5 @@ +function foo number>(x: T): T { + return undefined; +} + +foo(x => x.length); \ No newline at end of file diff --git a/tests/cases/compiler/inferentialTypingUsingApparentType2.ts b/tests/cases/compiler/inferentialTypingUsingApparentType2.ts new file mode 100644 index 00000000000..8290b14927d --- /dev/null +++ b/tests/cases/compiler/inferentialTypingUsingApparentType2.ts @@ -0,0 +1,5 @@ +function foo(x: T): T { + return undefined; +} + +foo({ m(x) { return x.length } }); \ No newline at end of file diff --git a/tests/cases/compiler/inferentialTypingUsingApparentType3.ts b/tests/cases/compiler/inferentialTypingUsingApparentType3.ts new file mode 100644 index 00000000000..d1734b0d100 --- /dev/null +++ b/tests/cases/compiler/inferentialTypingUsingApparentType3.ts @@ -0,0 +1,26 @@ +interface Field { + clean(input: T): T +} + +class CharField implements Field { + clean(input: string) { + return "Yup"; + } +} + +class NumberField implements Field { + clean(input: number) { + return 123; + } +} + +class ObjectField }> { + constructor(public fields: T) { } +} + +var person = new ObjectField({ + id: new NumberField(), + name: new CharField() +}); + +person.fields.id; \ No newline at end of file