diff --git a/tests/baselines/reference/functionExpressionContextualTyping1.js b/tests/baselines/reference/functionExpressionContextualTyping1.js new file mode 100644 index 0000000000000..8d60572b30f74 --- /dev/null +++ b/tests/baselines/reference/functionExpressionContextualTyping1.js @@ -0,0 +1,120 @@ +//// [functionExpressionContextualTyping1.ts] +// When a function expression with no type parameters and no parameter type annotations +// is contextually typed (section 4.19) by a type T and a contextual signature S can be extracted from T + +enum E { red, blue } + +// A contextual signature S is extracted from a function type T as follows: +// If T is a function type with exactly one call signature, and if that call signature is non- generic, S is that signature. + +var a0: (n: number, s: string) => number = (num, str) => { + num.toExponential(); + return 0; +} + +class Class { + foo() { } +} + +var a1: (c: Class) => number = (a1) => { + a1.foo(); + return 1; +} + +// A contextual signature S is extracted from a function type T as follows: +// If T is a union type, let U be the set of element types in T that have call signatures. +// If each type in U has exactly one call signature and that call signature is non- generic, +// and if all of the signatures are identical ignoring return types, +// then S is a signature with the same parameters and a union of the return types. +var b1: ((s: string, w: boolean) => void) | ((s: string, w: boolean) => string); +b1 = (k, h) => { }; +var b2: typeof a0 | ((n: number, s: string) => string); +b2 = (foo, bar) => { return foo + 1; } +b2 = (foo, bar) => { return "hello"; } +var b3: (name: string, num: number, boo: boolean) => void; +b3 = (name, number) => { }; + +var b4: (n: E) => string = (number = 1) => { return "hello"; }; +var b5: (n: {}) => string = (number = "string") => { return "hello"; }; + +// A contextual signature S is extracted from a function type T as follows: +// Otherwise, no contextual signature can be extracted from T and S is undefined. +var b6: ((s: string, w: boolean) => void) | ((n: number) => number); +var b7: ((s: string, w: boolean) => void) | ((s: string, w: number) => string); +b6 = (k) => { k.toLowerCase() }; +b6 = (i) => { + i.toExponential(); + return i; +}; // Per spec, no contextual signature can be extracted in this case. (Otherwise clause) +b7 = (j, m) => { }; // Per spec, no contextual signature can be extracted in this case. (Otherwise clause) + +class C { + constructor() { + var k: ((j: T, k: U) => (T|U)[]) | ((j: number,k :U) => number[]) = (j, k) => { + return [j, k]; + } // Per spec, no contextual signature can be extracted in this case. + } +} + +//// [functionExpressionContextualTyping1.js] +// When a function expression with no type parameters and no parameter type annotations +// is contextually typed (section 4.19) by a type T and a contextual signature S can be extracted from T +var E; +(function (E) { + E[E["red"] = 0] = "red"; + E[E["blue"] = 1] = "blue"; +})(E || (E = {})); +// A contextual signature S is extracted from a function type T as follows: +// If T is a function type with exactly one call signature, and if that call signature is non- generic, S is that signature. +var a0 = function (num, str) { + num.toExponential(); + return 0; +}; +var Class = (function () { + function Class() { + } + Class.prototype.foo = function () { }; + return Class; +})(); +var a1 = function (a1) { + a1.foo(); + return 1; +}; +// A contextual signature S is extracted from a function type T as follows: +// If T is a union type, let U be the set of element types in T that have call signatures. +// If each type in U has exactly one call signature and that call signature is non- generic, +// and if all of the signatures are identical ignoring return types, +// then S is a signature with the same parameters and a union of the return types. +var b1; +b1 = function (k, h) { }; +var b2; +b2 = function (foo, bar) { return foo + 1; }; +b2 = function (foo, bar) { return "hello"; }; +var b3; +b3 = function (name, number) { }; +var b4 = function (number) { + if (number === void 0) { number = 1; } + return "hello"; +}; +var b5 = function (number) { + if (number === void 0) { number = "string"; } + return "hello"; +}; +// A contextual signature S is extracted from a function type T as follows: +// Otherwise, no contextual signature can be extracted from T and S is undefined. +var b6; +var b7; +b6 = function (k) { k.toLowerCase(); }; +b6 = function (i) { + i.toExponential(); + return i; +}; // Per spec, no contextual signature can be extracted in this case. (Otherwise clause) +b7 = function (j, m) { }; // Per spec, no contextual signature can be extracted in this case. (Otherwise clause) +var C = (function () { + function C() { + var k = function (j, k) { + return [j, k]; + }; // Per spec, no contextual signature can be extracted in this case. + } + return C; +})(); diff --git a/tests/baselines/reference/functionExpressionContextualTyping1.symbols b/tests/baselines/reference/functionExpressionContextualTyping1.symbols new file mode 100644 index 0000000000000..6182e4bb9a8e4 --- /dev/null +++ b/tests/baselines/reference/functionExpressionContextualTyping1.symbols @@ -0,0 +1,169 @@ +=== tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping1.ts === +// When a function expression with no type parameters and no parameter type annotations +// is contextually typed (section 4.19) by a type T and a contextual signature S can be extracted from T + +enum E { red, blue } +>E : Symbol(E, Decl(functionExpressionContextualTyping1.ts, 0, 0)) +>red : Symbol(E.red, Decl(functionExpressionContextualTyping1.ts, 3, 8)) +>blue : Symbol(E.blue, Decl(functionExpressionContextualTyping1.ts, 3, 13)) + +// A contextual signature S is extracted from a function type T as follows: +// If T is a function type with exactly one call signature, and if that call signature is non- generic, S is that signature. + +var a0: (n: number, s: string) => number = (num, str) => { +>a0 : Symbol(a0, Decl(functionExpressionContextualTyping1.ts, 8, 3)) +>n : Symbol(n, Decl(functionExpressionContextualTyping1.ts, 8, 9)) +>s : Symbol(s, Decl(functionExpressionContextualTyping1.ts, 8, 19)) +>num : Symbol(num, Decl(functionExpressionContextualTyping1.ts, 8, 44)) +>str : Symbol(str, Decl(functionExpressionContextualTyping1.ts, 8, 48)) + + num.toExponential(); +>num.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, 469, 45)) +>num : Symbol(num, Decl(functionExpressionContextualTyping1.ts, 8, 44)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, 469, 45)) + + return 0; +} + +class Class { +>Class : Symbol(Class, Decl(functionExpressionContextualTyping1.ts, 11, 1)) +>T : Symbol(T, Decl(functionExpressionContextualTyping1.ts, 13, 12)) + + foo() { } +>foo : Symbol(foo, Decl(functionExpressionContextualTyping1.ts, 13, 16)) +} + +var a1: (c: Class) => number = (a1) => { +>a1 : Symbol(a1, Decl(functionExpressionContextualTyping1.ts, 17, 3)) +>c : Symbol(c, Decl(functionExpressionContextualTyping1.ts, 17, 9)) +>Class : Symbol(Class, Decl(functionExpressionContextualTyping1.ts, 11, 1)) +>Number : Symbol(Number, Decl(lib.d.ts, 456, 40), Decl(lib.d.ts, 518, 11)) +>a1 : Symbol(a1, Decl(functionExpressionContextualTyping1.ts, 17, 40)) + + a1.foo(); +>a1.foo : Symbol(Class.foo, Decl(functionExpressionContextualTyping1.ts, 13, 16)) +>a1 : Symbol(a1, Decl(functionExpressionContextualTyping1.ts, 17, 40)) +>foo : Symbol(Class.foo, Decl(functionExpressionContextualTyping1.ts, 13, 16)) + + return 1; +} + +// A contextual signature S is extracted from a function type T as follows: +// If T is a union type, let U be the set of element types in T that have call signatures. +// If each type in U has exactly one call signature and that call signature is non- generic, +// and if all of the signatures are identical ignoring return types, +// then S is a signature with the same parameters and a union of the return types. +var b1: ((s: string, w: boolean) => void) | ((s: string, w: boolean) => string); +>b1 : Symbol(b1, Decl(functionExpressionContextualTyping1.ts, 27, 3)) +>s : Symbol(s, Decl(functionExpressionContextualTyping1.ts, 27, 10)) +>w : Symbol(w, Decl(functionExpressionContextualTyping1.ts, 27, 20)) +>s : Symbol(s, Decl(functionExpressionContextualTyping1.ts, 27, 46)) +>w : Symbol(w, Decl(functionExpressionContextualTyping1.ts, 27, 56)) + +b1 = (k, h) => { }; +>b1 : Symbol(b1, Decl(functionExpressionContextualTyping1.ts, 27, 3)) +>k : Symbol(k, Decl(functionExpressionContextualTyping1.ts, 28, 6)) +>h : Symbol(h, Decl(functionExpressionContextualTyping1.ts, 28, 8)) + +var b2: typeof a0 | ((n: number, s: string) => string); +>b2 : Symbol(b2, Decl(functionExpressionContextualTyping1.ts, 29, 3)) +>a0 : Symbol(a0, Decl(functionExpressionContextualTyping1.ts, 8, 3)) +>n : Symbol(n, Decl(functionExpressionContextualTyping1.ts, 29, 22)) +>s : Symbol(s, Decl(functionExpressionContextualTyping1.ts, 29, 32)) + +b2 = (foo, bar) => { return foo + 1; } +>b2 : Symbol(b2, Decl(functionExpressionContextualTyping1.ts, 29, 3)) +>foo : Symbol(foo, Decl(functionExpressionContextualTyping1.ts, 30, 6)) +>bar : Symbol(bar, Decl(functionExpressionContextualTyping1.ts, 30, 10)) +>foo : Symbol(foo, Decl(functionExpressionContextualTyping1.ts, 30, 6)) + +b2 = (foo, bar) => { return "hello"; } +>b2 : Symbol(b2, Decl(functionExpressionContextualTyping1.ts, 29, 3)) +>foo : Symbol(foo, Decl(functionExpressionContextualTyping1.ts, 31, 6)) +>bar : Symbol(bar, Decl(functionExpressionContextualTyping1.ts, 31, 10)) + +var b3: (name: string, num: number, boo: boolean) => void; +>b3 : Symbol(b3, Decl(functionExpressionContextualTyping1.ts, 32, 3)) +>name : Symbol(name, Decl(functionExpressionContextualTyping1.ts, 32, 9)) +>num : Symbol(num, Decl(functionExpressionContextualTyping1.ts, 32, 22)) +>boo : Symbol(boo, Decl(functionExpressionContextualTyping1.ts, 32, 35)) + +b3 = (name, number) => { }; +>b3 : Symbol(b3, Decl(functionExpressionContextualTyping1.ts, 32, 3)) +>name : Symbol(name, Decl(functionExpressionContextualTyping1.ts, 33, 6)) +>number : Symbol(number, Decl(functionExpressionContextualTyping1.ts, 33, 11)) + +var b4: (n: E) => string = (number = 1) => { return "hello"; }; +>b4 : Symbol(b4, Decl(functionExpressionContextualTyping1.ts, 35, 3)) +>n : Symbol(n, Decl(functionExpressionContextualTyping1.ts, 35, 9)) +>E : Symbol(E, Decl(functionExpressionContextualTyping1.ts, 0, 0)) +>number : Symbol(number, Decl(functionExpressionContextualTyping1.ts, 35, 28)) + +var b5: (n: {}) => string = (number = "string") => { return "hello"; }; +>b5 : Symbol(b5, Decl(functionExpressionContextualTyping1.ts, 36, 3)) +>n : Symbol(n, Decl(functionExpressionContextualTyping1.ts, 36, 9)) +>number : Symbol(number, Decl(functionExpressionContextualTyping1.ts, 36, 29)) + +// A contextual signature S is extracted from a function type T as follows: +// Otherwise, no contextual signature can be extracted from T and S is undefined. +var b6: ((s: string, w: boolean) => void) | ((n: number) => number); +>b6 : Symbol(b6, Decl(functionExpressionContextualTyping1.ts, 40, 3)) +>s : Symbol(s, Decl(functionExpressionContextualTyping1.ts, 40, 10)) +>w : Symbol(w, Decl(functionExpressionContextualTyping1.ts, 40, 20)) +>n : Symbol(n, Decl(functionExpressionContextualTyping1.ts, 40, 46)) + +var b7: ((s: string, w: boolean) => void) | ((s: string, w: number) => string); +>b7 : Symbol(b7, Decl(functionExpressionContextualTyping1.ts, 41, 3)) +>s : Symbol(s, Decl(functionExpressionContextualTyping1.ts, 41, 10)) +>w : Symbol(w, Decl(functionExpressionContextualTyping1.ts, 41, 20)) +>s : Symbol(s, Decl(functionExpressionContextualTyping1.ts, 41, 46)) +>w : Symbol(w, Decl(functionExpressionContextualTyping1.ts, 41, 56)) + +b6 = (k) => { k.toLowerCase() }; +>b6 : Symbol(b6, Decl(functionExpressionContextualTyping1.ts, 40, 3)) +>k : Symbol(k, Decl(functionExpressionContextualTyping1.ts, 42, 6)) +>k : Symbol(k, Decl(functionExpressionContextualTyping1.ts, 42, 6)) + +b6 = (i) => { +>b6 : Symbol(b6, Decl(functionExpressionContextualTyping1.ts, 40, 3)) +>i : Symbol(i, Decl(functionExpressionContextualTyping1.ts, 43, 6)) + + i.toExponential(); +>i : Symbol(i, Decl(functionExpressionContextualTyping1.ts, 43, 6)) + + return i; +>i : Symbol(i, Decl(functionExpressionContextualTyping1.ts, 43, 6)) + +}; // Per spec, no contextual signature can be extracted in this case. (Otherwise clause) +b7 = (j, m) => { }; // Per spec, no contextual signature can be extracted in this case. (Otherwise clause) +>b7 : Symbol(b7, Decl(functionExpressionContextualTyping1.ts, 41, 3)) +>j : Symbol(j, Decl(functionExpressionContextualTyping1.ts, 47, 6)) +>m : Symbol(m, Decl(functionExpressionContextualTyping1.ts, 47, 8)) + +class C { +>C : Symbol(C, Decl(functionExpressionContextualTyping1.ts, 47, 19)) +>T : Symbol(T, Decl(functionExpressionContextualTyping1.ts, 49, 8)) +>U : Symbol(U, Decl(functionExpressionContextualTyping1.ts, 49, 10)) + + constructor() { + var k: ((j: T, k: U) => (T|U)[]) | ((j: number,k :U) => number[]) = (j, k) => { +>k : Symbol(k, Decl(functionExpressionContextualTyping1.ts, 51, 11)) +>j : Symbol(j, Decl(functionExpressionContextualTyping1.ts, 51, 17)) +>T : Symbol(T, Decl(functionExpressionContextualTyping1.ts, 49, 8)) +>k : Symbol(k, Decl(functionExpressionContextualTyping1.ts, 51, 22)) +>U : Symbol(U, Decl(functionExpressionContextualTyping1.ts, 49, 10)) +>T : Symbol(T, Decl(functionExpressionContextualTyping1.ts, 49, 8)) +>U : Symbol(U, Decl(functionExpressionContextualTyping1.ts, 49, 10)) +>j : Symbol(j, Decl(functionExpressionContextualTyping1.ts, 51, 45)) +>k : Symbol(k, Decl(functionExpressionContextualTyping1.ts, 51, 55)) +>U : Symbol(U, Decl(functionExpressionContextualTyping1.ts, 49, 10)) +>j : Symbol(j, Decl(functionExpressionContextualTyping1.ts, 51, 77)) +>k : Symbol(k, Decl(functionExpressionContextualTyping1.ts, 51, 79)) + + return [j, k]; +>j : Symbol(j, Decl(functionExpressionContextualTyping1.ts, 51, 77)) +>k : Symbol(k, Decl(functionExpressionContextualTyping1.ts, 51, 79)) + + } // Per spec, no contextual signature can be extracted in this case. + } +} diff --git a/tests/baselines/reference/functionExpressionContextualTyping1.types b/tests/baselines/reference/functionExpressionContextualTyping1.types new file mode 100644 index 0000000000000..61d16bf6a4fdd --- /dev/null +++ b/tests/baselines/reference/functionExpressionContextualTyping1.types @@ -0,0 +1,206 @@ +=== tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping1.ts === +// When a function expression with no type parameters and no parameter type annotations +// is contextually typed (section 4.19) by a type T and a contextual signature S can be extracted from T + +enum E { red, blue } +>E : E +>red : E +>blue : E + +// A contextual signature S is extracted from a function type T as follows: +// If T is a function type with exactly one call signature, and if that call signature is non- generic, S is that signature. + +var a0: (n: number, s: string) => number = (num, str) => { +>a0 : (n: number, s: string) => number +>n : number +>s : string +>(num, str) => { num.toExponential(); return 0;} : (num: number, str: string) => number +>num : number +>str : string + + num.toExponential(); +>num.toExponential() : string +>num.toExponential : (fractionDigits?: number) => string +>num : number +>toExponential : (fractionDigits?: number) => string + + return 0; +>0 : number +} + +class Class { +>Class : Class +>T : T + + foo() { } +>foo : () => void +} + +var a1: (c: Class) => number = (a1) => { +>a1 : (c: Class) => number +>c : Class +>Class : Class +>Number : Number +>(a1) => { a1.foo(); return 1;} : (a1: Class) => number +>a1 : Class + + a1.foo(); +>a1.foo() : void +>a1.foo : () => void +>a1 : Class +>foo : () => void + + return 1; +>1 : number +} + +// A contextual signature S is extracted from a function type T as follows: +// If T is a union type, let U be the set of element types in T that have call signatures. +// If each type in U has exactly one call signature and that call signature is non- generic, +// and if all of the signatures are identical ignoring return types, +// then S is a signature with the same parameters and a union of the return types. +var b1: ((s: string, w: boolean) => void) | ((s: string, w: boolean) => string); +>b1 : ((s: string, w: boolean) => void) | ((s: string, w: boolean) => string) +>s : string +>w : boolean +>s : string +>w : boolean + +b1 = (k, h) => { }; +>b1 = (k, h) => { } : (k: string, h: boolean) => void +>b1 : ((s: string, w: boolean) => void) | ((s: string, w: boolean) => string) +>(k, h) => { } : (k: string, h: boolean) => void +>k : string +>h : boolean + +var b2: typeof a0 | ((n: number, s: string) => string); +>b2 : ((n: number, s: string) => number) | ((n: number, s: string) => string) +>a0 : (n: number, s: string) => number +>n : number +>s : string + +b2 = (foo, bar) => { return foo + 1; } +>b2 = (foo, bar) => { return foo + 1; } : (foo: number, bar: string) => number +>b2 : ((n: number, s: string) => number) | ((n: number, s: string) => string) +>(foo, bar) => { return foo + 1; } : (foo: number, bar: string) => number +>foo : number +>bar : string +>foo + 1 : number +>foo : number +>1 : number + +b2 = (foo, bar) => { return "hello"; } +>b2 = (foo, bar) => { return "hello"; } : (foo: number, bar: string) => string +>b2 : ((n: number, s: string) => number) | ((n: number, s: string) => string) +>(foo, bar) => { return "hello"; } : (foo: number, bar: string) => string +>foo : number +>bar : string +>"hello" : string + +var b3: (name: string, num: number, boo: boolean) => void; +>b3 : (name: string, num: number, boo: boolean) => void +>name : string +>num : number +>boo : boolean + +b3 = (name, number) => { }; +>b3 = (name, number) => { } : (name: string, number: number) => void +>b3 : (name: string, num: number, boo: boolean) => void +>(name, number) => { } : (name: string, number: number) => void +>name : string +>number : number + +var b4: (n: E) => string = (number = 1) => { return "hello"; }; +>b4 : (n: E) => string +>n : E +>E : E +>(number = 1) => { return "hello"; } : (number?: E) => string +>number : E +>1 : number +>"hello" : string + +var b5: (n: {}) => string = (number = "string") => { return "hello"; }; +>b5 : (n: {}) => string +>n : {} +>(number = "string") => { return "hello"; } : (number?: {}) => string +>number : {} +>"string" : string +>"hello" : string + +// A contextual signature S is extracted from a function type T as follows: +// Otherwise, no contextual signature can be extracted from T and S is undefined. +var b6: ((s: string, w: boolean) => void) | ((n: number) => number); +>b6 : ((s: string, w: boolean) => void) | ((n: number) => number) +>s : string +>w : boolean +>n : number + +var b7: ((s: string, w: boolean) => void) | ((s: string, w: number) => string); +>b7 : ((s: string, w: boolean) => void) | ((s: string, w: number) => string) +>s : string +>w : boolean +>s : string +>w : number + +b6 = (k) => { k.toLowerCase() }; +>b6 = (k) => { k.toLowerCase() } : (k: any) => void +>b6 : ((s: string, w: boolean) => void) | ((n: number) => number) +>(k) => { k.toLowerCase() } : (k: any) => void +>k : any +>k.toLowerCase() : any +>k.toLowerCase : any +>k : any +>toLowerCase : any + +b6 = (i) => { +>b6 = (i) => { i.toExponential(); return i;} : (i: any) => any +>b6 : ((s: string, w: boolean) => void) | ((n: number) => number) +>(i) => { i.toExponential(); return i;} : (i: any) => any +>i : any + + i.toExponential(); +>i.toExponential() : any +>i.toExponential : any +>i : any +>toExponential : any + + return i; +>i : any + +}; // Per spec, no contextual signature can be extracted in this case. (Otherwise clause) +b7 = (j, m) => { }; // Per spec, no contextual signature can be extracted in this case. (Otherwise clause) +>b7 = (j, m) => { } : (j: any, m: any) => void +>b7 : ((s: string, w: boolean) => void) | ((s: string, w: number) => string) +>(j, m) => { } : (j: any, m: any) => void +>j : any +>m : any + +class C { +>C : C +>T : T +>U : U + + constructor() { + var k: ((j: T, k: U) => (T|U)[]) | ((j: number,k :U) => number[]) = (j, k) => { +>k : ((j: T, k: U) => (T | U)[]) | ((j: number, k: U) => number[]) +>j : T +>T : T +>k : U +>U : U +>T : T +>U : U +>j : number +>k : U +>U : U +>(j, k) => { return [j, k]; } : (j: any, k: any) => any[] +>j : any +>k : any + + return [j, k]; +>[j, k] : any[] +>j : any +>k : any + + } // Per spec, no contextual signature can be extracted in this case. + } +} diff --git a/tests/baselines/reference/functionExpressionContextualTyping2.errors.txt b/tests/baselines/reference/functionExpressionContextualTyping2.errors.txt new file mode 100644 index 0000000000000..6a3a7998f099d --- /dev/null +++ b/tests/baselines/reference/functionExpressionContextualTyping2.errors.txt @@ -0,0 +1,21 @@ +tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping2.ts(11,1): error TS2322: Type '(foo: number, bar: string) => boolean' is not assignable to type '((n: number, s: string) => number) | ((n: number, s: string) => string)'. + Type '(foo: number, bar: string) => boolean' is not assignable to type '(n: number, s: string) => string'. + Type 'boolean' is not assignable to type 'string'. + + +==== tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping2.ts (1 errors) ==== + // A contextual signature S is extracted from a function type T as follows: + // If T is a function type with exactly one call signature, and if that call signature is non- generic, S is that signature. + // If T is a union type, let U be the set of element types in T that have call signatures. + // If each type in U has exactly one call signature and that call signature is non- generic, + // and if all of the signatures are identical ignoring return types, then S is a signature + // with the same parameters and a union of the return types. + // Otherwise, no contextual signature can be extracted from T and S is undefined. + + var a0: (n: number, s: string) => number + var a1: typeof a0 | ((n: number, s: string) => string); + a1 = (foo, bar) => { return true; } // Error + ~~ +!!! error TS2322: Type '(foo: number, bar: string) => boolean' is not assignable to type '((n: number, s: string) => number) | ((n: number, s: string) => string)'. +!!! error TS2322: Type '(foo: number, bar: string) => boolean' is not assignable to type '(n: number, s: string) => string'. +!!! error TS2322: Type 'boolean' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/functionExpressionContextualTyping2.js b/tests/baselines/reference/functionExpressionContextualTyping2.js new file mode 100644 index 0000000000000..dae30a790360b --- /dev/null +++ b/tests/baselines/reference/functionExpressionContextualTyping2.js @@ -0,0 +1,24 @@ +//// [functionExpressionContextualTyping2.ts] +// A contextual signature S is extracted from a function type T as follows: +// If T is a function type with exactly one call signature, and if that call signature is non- generic, S is that signature. +// If T is a union type, let U be the set of element types in T that have call signatures. +// If each type in U has exactly one call signature and that call signature is non- generic, +// and if all of the signatures are identical ignoring return types, then S is a signature +// with the same parameters and a union of the return types. +// Otherwise, no contextual signature can be extracted from T and S is undefined. + +var a0: (n: number, s: string) => number +var a1: typeof a0 | ((n: number, s: string) => string); +a1 = (foo, bar) => { return true; } // Error + +//// [functionExpressionContextualTyping2.js] +// A contextual signature S is extracted from a function type T as follows: +// If T is a function type with exactly one call signature, and if that call signature is non- generic, S is that signature. +// If T is a union type, let U be the set of element types in T that have call signatures. +// If each type in U has exactly one call signature and that call signature is non- generic, +// and if all of the signatures are identical ignoring return types, then S is a signature +// with the same parameters and a union of the return types. +// Otherwise, no contextual signature can be extracted from T and S is undefined. +var a0; +var a1; +a1 = function (foo, bar) { return true; }; // Error diff --git a/tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping1.ts b/tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping1.ts new file mode 100644 index 0000000000000..ea8e60cb5b922 --- /dev/null +++ b/tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping1.ts @@ -0,0 +1,56 @@ +// When a function expression with no type parameters and no parameter type annotations +// is contextually typed (section 4.19) by a type T and a contextual signature S can be extracted from T + +enum E { red, blue } + +// A contextual signature S is extracted from a function type T as follows: +// If T is a function type with exactly one call signature, and if that call signature is non- generic, S is that signature. + +var a0: (n: number, s: string) => number = (num, str) => { + num.toExponential(); + return 0; +} + +class Class { + foo() { } +} + +var a1: (c: Class) => number = (a1) => { + a1.foo(); + return 1; +} + +// A contextual signature S is extracted from a function type T as follows: +// If T is a union type, let U be the set of element types in T that have call signatures. +// If each type in U has exactly one call signature and that call signature is non- generic, +// and if all of the signatures are identical ignoring return types, +// then S is a signature with the same parameters and a union of the return types. +var b1: ((s: string, w: boolean) => void) | ((s: string, w: boolean) => string); +b1 = (k, h) => { }; +var b2: typeof a0 | ((n: number, s: string) => string); +b2 = (foo, bar) => { return foo + 1; } +b2 = (foo, bar) => { return "hello"; } +var b3: (name: string, num: number, boo: boolean) => void; +b3 = (name, number) => { }; + +var b4: (n: E) => string = (number = 1) => { return "hello"; }; +var b5: (n: {}) => string = (number = "string") => { return "hello"; }; + +// A contextual signature S is extracted from a function type T as follows: +// Otherwise, no contextual signature can be extracted from T and S is undefined. +var b6: ((s: string, w: boolean) => void) | ((n: number) => number); +var b7: ((s: string, w: boolean) => void) | ((s: string, w: number) => string); +b6 = (k) => { k.toLowerCase() }; +b6 = (i) => { + i.toExponential(); + return i; +}; // Per spec, no contextual signature can be extracted in this case. (Otherwise clause) +b7 = (j, m) => { }; // Per spec, no contextual signature can be extracted in this case. (Otherwise clause) + +class C { + constructor() { + var k: ((j: T, k: U) => (T|U)[]) | ((j: number,k :U) => number[]) = (j, k) => { + return [j, k]; + } // Per spec, no contextual signature can be extracted in this case. + } +} \ No newline at end of file diff --git a/tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping2.ts b/tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping2.ts new file mode 100644 index 0000000000000..1b88c1a8cfbdc --- /dev/null +++ b/tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping2.ts @@ -0,0 +1,11 @@ +// A contextual signature S is extracted from a function type T as follows: +// If T is a function type with exactly one call signature, and if that call signature is non- generic, S is that signature. +// If T is a union type, let U be the set of element types in T that have call signatures. +// If each type in U has exactly one call signature and that call signature is non- generic, +// and if all of the signatures are identical ignoring return types, then S is a signature +// with the same parameters and a union of the return types. +// Otherwise, no contextual signature can be extracted from T and S is undefined. + +var a0: (n: number, s: string) => number +var a1: typeof a0 | ((n: number, s: string) => string); +a1 = (foo, bar) => { return true; } // Error \ No newline at end of file