From 451f65332c40fe93ccd703f075dfb85f46d162dc Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 19 Feb 2019 07:02:37 -1000 Subject: [PATCH 1/3] Improve contextual typing by generic rest parameter --- src/compiler/checker.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3bd089aff6f19..6711d56fe30ed 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10669,9 +10669,9 @@ namespace ts { return !!(mapper).typeParameters; } - function cloneTypeMapper(mapper: TypeMapper): TypeMapper { + function cloneTypeMapper(mapper: TypeMapper, extraFlags: InferenceFlags = 0): TypeMapper { return mapper && isInferenceContext(mapper) ? - createInferenceContext(mapper.typeParameters, mapper.signature, mapper.flags | InferenceFlags.NoDefault, mapper.compareTypes, mapper.inferences) : + createInferenceContext(mapper.typeParameters, mapper.signature, mapper.flags | extraFlags, mapper.compareTypes, mapper.inferences) : mapper; } @@ -19984,7 +19984,7 @@ namespace ts { // We clone the contextual mapper to avoid disturbing a resolution in progress for an // outer call expression. Effectively we just want a snapshot of whatever has been // inferred for any outer call expression so far. - const instantiatedType = instantiateType(contextualType, cloneTypeMapper(getContextualMapper(node))); + const instantiatedType = instantiateType(contextualType, cloneTypeMapper(getContextualMapper(node), InferenceFlags.NoDefault)); // If the contextual type is a generic function type with a single call signature, we // instantiate the type with its own type parameters and type arguments. This ensures that // the type parameters are not erased to type any during type inference such that they can @@ -21652,6 +21652,17 @@ namespace ts { } } } + const restType = getEffectiveRestType(context); + if (restType && restType.flags & TypeFlags.TypeParameter) { + // The contextual signature has a generic rest parameter. We first instantiate the contextual + // signature (without fixing type parameters) and assign types to contextually typed parameters. + const instantiatedContext = instantiateSignature(context, cloneTypeMapper(mapper)); + assignContextualParameterTypes(signature, instantiatedContext); + // We then infer from a tuple type representing the parameters that correspond to the contextual + // rest parameter. + const restPos = getParameterCount(context) - 1; + inferTypes((mapper).inferences, getRestTypeAtPosition(signature, restPos), restType); + } } function assignContextualParameterTypes(signature: Signature, context: Signature) { From f19191b0811a7ad8245b4603aa98eba507fcbc3f Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 19 Feb 2019 07:02:50 -1000 Subject: [PATCH 2/3] Add tests --- .../types/rest/restTuplesFromContextualTypes.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/cases/conformance/types/rest/restTuplesFromContextualTypes.ts b/tests/cases/conformance/types/rest/restTuplesFromContextualTypes.ts index d5623a000a20d..85421a7697b1c 100644 --- a/tests/cases/conformance/types/rest/restTuplesFromContextualTypes.ts +++ b/tests/cases/conformance/types/rest/restTuplesFromContextualTypes.ts @@ -59,6 +59,21 @@ function f4(t: T) { f((a, b, ...x) => {}); } +declare function f5(f: (...args: T) => U): (...args: T) => U; + +let g0 = f5(() => "hello"); +let g1 = f5((x, y) => 42); +let g2 = f5((x: number, y) => 42); +let g3 = f5((x: number, y: number) => x + y); +let g4 = f5((...args) => true); + +declare function pipe(f: (...args: A) => B, g: (x: B) => C): (...args: A) => C; + +let g5 = pipe(() => true, b => 42); +let g6 = pipe(x => "hello", s => s.length); +let g7 = pipe((x, y) => 42, x => "" + x); +let g8 = pipe((x: number, y: string) => 42, x => "" + x); + // Repro from #25288 declare var tuple: [number, string]; From d0cb0471897d6d357f162da10e871c00b5633a60 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 19 Feb 2019 07:04:31 -1000 Subject: [PATCH 3/3] Accept new baselines --- .../restTuplesFromContextualTypes.errors.txt | 15 ++ .../restTuplesFromContextualTypes.js | 41 +++++ .../restTuplesFromContextualTypes.symbols | 146 ++++++++++++++---- .../restTuplesFromContextualTypes.types | 109 +++++++++++++ 4 files changed, 282 insertions(+), 29 deletions(-) diff --git a/tests/baselines/reference/restTuplesFromContextualTypes.errors.txt b/tests/baselines/reference/restTuplesFromContextualTypes.errors.txt index 2b94b57f462b6..5f2c299735b0b 100644 --- a/tests/baselines/reference/restTuplesFromContextualTypes.errors.txt +++ b/tests/baselines/reference/restTuplesFromContextualTypes.errors.txt @@ -68,6 +68,21 @@ tests/cases/conformance/types/rest/restTuplesFromContextualTypes.ts(56,7): error !!! error TS2345: Property '0' is missing in type 'any[]' but required in type '[T[0], ...T[number][]]'. } + declare function f5(f: (...args: T) => U): (...args: T) => U; + + let g0 = f5(() => "hello"); + let g1 = f5((x, y) => 42); + let g2 = f5((x: number, y) => 42); + let g3 = f5((x: number, y: number) => x + y); + let g4 = f5((...args) => true); + + declare function pipe(f: (...args: A) => B, g: (x: B) => C): (...args: A) => C; + + let g5 = pipe(() => true, b => 42); + let g6 = pipe(x => "hello", s => s.length); + let g7 = pipe((x, y) => 42, x => "" + x); + let g8 = pipe((x: number, y: string) => 42, x => "" + x); + // Repro from #25288 declare var tuple: [number, string]; diff --git a/tests/baselines/reference/restTuplesFromContextualTypes.js b/tests/baselines/reference/restTuplesFromContextualTypes.js index 34e75fcea6e30..affe55603bf5e 100644 --- a/tests/baselines/reference/restTuplesFromContextualTypes.js +++ b/tests/baselines/reference/restTuplesFromContextualTypes.js @@ -57,6 +57,21 @@ function f4(t: T) { f((a, b, ...x) => {}); } +declare function f5(f: (...args: T) => U): (...args: T) => U; + +let g0 = f5(() => "hello"); +let g1 = f5((x, y) => 42); +let g2 = f5((x: number, y) => 42); +let g3 = f5((x: number, y: number) => x + y); +let g4 = f5((...args) => true); + +declare function pipe(f: (...args: A) => B, g: (x: B) => C): (...args: A) => C; + +let g5 = pipe(() => true, b => 42); +let g6 = pipe(x => "hello", s => s.length); +let g7 = pipe((x, y) => 42, x => "" + x); +let g8 = pipe((x: number, y: string) => 42, x => "" + x); + // Repro from #25288 declare var tuple: [number, string]; @@ -275,6 +290,21 @@ function f4(t) { } }); } +var g0 = f5(function () { return "hello"; }); +var g1 = f5(function (x, y) { return 42; }); +var g2 = f5(function (x, y) { return 42; }); +var g3 = f5(function (x, y) { return x + y; }); +var g4 = f5(function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + return true; +}); +var g5 = pipe(function () { return true; }, function (b) { return 42; }); +var g6 = pipe(function (x) { return "hello"; }, function (s) { return s.length; }); +var g7 = pipe(function (x, y) { return 42; }, function (x) { return "" + x; }); +var g8 = pipe(function (x, y) { return 42; }, function (x) { return "" + x; }); (function foo(a, b) { }.apply(void 0, tuple)); (function foo() { var rest = []; @@ -309,6 +339,17 @@ declare function f2(cb: (...args: typeof t2) => void): void; declare const t3: [boolean, ...string[]]; declare function f3(cb: (x: number, ...args: typeof t3) => void): void; declare function f4(t: T): void; +declare function f5(f: (...args: T) => U): (...args: T) => U; +declare let g0: () => string; +declare let g1: (x: any, y: any) => number; +declare let g2: (x: number, y: any) => number; +declare let g3: (x: number, y: number) => number; +declare let g4: (...args: any[]) => boolean; +declare function pipe(f: (...args: A) => B, g: (x: B) => C): (...args: A) => C; +declare let g5: () => number; +declare let g6: (x: any) => number; +declare let g7: (x: any, y: any) => string; +declare let g8: (x: number, y: string) => string; declare var tuple: [number, string]; declare function take(cb: (a: number, b: string) => void): void; declare type ArgsUnion = [number, string] | [number, Error]; diff --git a/tests/baselines/reference/restTuplesFromContextualTypes.symbols b/tests/baselines/reference/restTuplesFromContextualTypes.symbols index c58e8cabcae7d..8cde9f489076c 100644 --- a/tests/baselines/reference/restTuplesFromContextualTypes.symbols +++ b/tests/baselines/reference/restTuplesFromContextualTypes.symbols @@ -238,67 +238,155 @@ function f4(t: T) { >x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 55, 12)) } +declare function f5(f: (...args: T) => U): (...args: T) => U; +>f5 : Symbol(f5, Decl(restTuplesFromContextualTypes.ts, 56, 1)) +>T : Symbol(T, Decl(restTuplesFromContextualTypes.ts, 58, 20)) +>U : Symbol(U, Decl(restTuplesFromContextualTypes.ts, 58, 36)) +>f : Symbol(f, Decl(restTuplesFromContextualTypes.ts, 58, 40)) +>args : Symbol(args, Decl(restTuplesFromContextualTypes.ts, 58, 44)) +>T : Symbol(T, Decl(restTuplesFromContextualTypes.ts, 58, 20)) +>U : Symbol(U, Decl(restTuplesFromContextualTypes.ts, 58, 36)) +>args : Symbol(args, Decl(restTuplesFromContextualTypes.ts, 58, 64)) +>T : Symbol(T, Decl(restTuplesFromContextualTypes.ts, 58, 20)) +>U : Symbol(U, Decl(restTuplesFromContextualTypes.ts, 58, 36)) + +let g0 = f5(() => "hello"); +>g0 : Symbol(g0, Decl(restTuplesFromContextualTypes.ts, 60, 3)) +>f5 : Symbol(f5, Decl(restTuplesFromContextualTypes.ts, 56, 1)) + +let g1 = f5((x, y) => 42); +>g1 : Symbol(g1, Decl(restTuplesFromContextualTypes.ts, 61, 3)) +>f5 : Symbol(f5, Decl(restTuplesFromContextualTypes.ts, 56, 1)) +>x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 61, 13)) +>y : Symbol(y, Decl(restTuplesFromContextualTypes.ts, 61, 15)) + +let g2 = f5((x: number, y) => 42); +>g2 : Symbol(g2, Decl(restTuplesFromContextualTypes.ts, 62, 3)) +>f5 : Symbol(f5, Decl(restTuplesFromContextualTypes.ts, 56, 1)) +>x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 62, 13)) +>y : Symbol(y, Decl(restTuplesFromContextualTypes.ts, 62, 23)) + +let g3 = f5((x: number, y: number) => x + y); +>g3 : Symbol(g3, Decl(restTuplesFromContextualTypes.ts, 63, 3)) +>f5 : Symbol(f5, Decl(restTuplesFromContextualTypes.ts, 56, 1)) +>x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 63, 13)) +>y : Symbol(y, Decl(restTuplesFromContextualTypes.ts, 63, 23)) +>x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 63, 13)) +>y : Symbol(y, Decl(restTuplesFromContextualTypes.ts, 63, 23)) + +let g4 = f5((...args) => true); +>g4 : Symbol(g4, Decl(restTuplesFromContextualTypes.ts, 64, 3)) +>f5 : Symbol(f5, Decl(restTuplesFromContextualTypes.ts, 56, 1)) +>args : Symbol(args, Decl(restTuplesFromContextualTypes.ts, 64, 13)) + +declare function pipe(f: (...args: A) => B, g: (x: B) => C): (...args: A) => C; +>pipe : Symbol(pipe, Decl(restTuplesFromContextualTypes.ts, 64, 31)) +>A : Symbol(A, Decl(restTuplesFromContextualTypes.ts, 66, 22)) +>B : Symbol(B, Decl(restTuplesFromContextualTypes.ts, 66, 38)) +>C : Symbol(C, Decl(restTuplesFromContextualTypes.ts, 66, 41)) +>f : Symbol(f, Decl(restTuplesFromContextualTypes.ts, 66, 45)) +>args : Symbol(args, Decl(restTuplesFromContextualTypes.ts, 66, 49)) +>A : Symbol(A, Decl(restTuplesFromContextualTypes.ts, 66, 22)) +>B : Symbol(B, Decl(restTuplesFromContextualTypes.ts, 66, 38)) +>g : Symbol(g, Decl(restTuplesFromContextualTypes.ts, 66, 66)) +>x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 66, 71)) +>B : Symbol(B, Decl(restTuplesFromContextualTypes.ts, 66, 38)) +>C : Symbol(C, Decl(restTuplesFromContextualTypes.ts, 66, 41)) +>args : Symbol(args, Decl(restTuplesFromContextualTypes.ts, 66, 85)) +>A : Symbol(A, Decl(restTuplesFromContextualTypes.ts, 66, 22)) +>C : Symbol(C, Decl(restTuplesFromContextualTypes.ts, 66, 41)) + +let g5 = pipe(() => true, b => 42); +>g5 : Symbol(g5, Decl(restTuplesFromContextualTypes.ts, 68, 3)) +>pipe : Symbol(pipe, Decl(restTuplesFromContextualTypes.ts, 64, 31)) +>b : Symbol(b, Decl(restTuplesFromContextualTypes.ts, 68, 25)) + +let g6 = pipe(x => "hello", s => s.length); +>g6 : Symbol(g6, Decl(restTuplesFromContextualTypes.ts, 69, 3)) +>pipe : Symbol(pipe, Decl(restTuplesFromContextualTypes.ts, 64, 31)) +>x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 69, 14)) +>s : Symbol(s, Decl(restTuplesFromContextualTypes.ts, 69, 27)) +>s.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) +>s : Symbol(s, Decl(restTuplesFromContextualTypes.ts, 69, 27)) +>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) + +let g7 = pipe((x, y) => 42, x => "" + x); +>g7 : Symbol(g7, Decl(restTuplesFromContextualTypes.ts, 70, 3)) +>pipe : Symbol(pipe, Decl(restTuplesFromContextualTypes.ts, 64, 31)) +>x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 70, 15)) +>y : Symbol(y, Decl(restTuplesFromContextualTypes.ts, 70, 17)) +>x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 70, 27)) +>x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 70, 27)) + +let g8 = pipe((x: number, y: string) => 42, x => "" + x); +>g8 : Symbol(g8, Decl(restTuplesFromContextualTypes.ts, 71, 3)) +>pipe : Symbol(pipe, Decl(restTuplesFromContextualTypes.ts, 64, 31)) +>x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 71, 15)) +>y : Symbol(y, Decl(restTuplesFromContextualTypes.ts, 71, 25)) +>x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 71, 43)) +>x : Symbol(x, Decl(restTuplesFromContextualTypes.ts, 71, 43)) + // Repro from #25288 declare var tuple: [number, string]; ->tuple : Symbol(tuple, Decl(restTuplesFromContextualTypes.ts, 60, 11)) +>tuple : Symbol(tuple, Decl(restTuplesFromContextualTypes.ts, 75, 11)) (function foo(a, b){}(...tuple)); ->foo : Symbol(foo, Decl(restTuplesFromContextualTypes.ts, 61, 1)) ->a : Symbol(a, Decl(restTuplesFromContextualTypes.ts, 61, 14)) ->b : Symbol(b, Decl(restTuplesFromContextualTypes.ts, 61, 16)) ->tuple : Symbol(tuple, Decl(restTuplesFromContextualTypes.ts, 60, 11)) +>foo : Symbol(foo, Decl(restTuplesFromContextualTypes.ts, 76, 1)) +>a : Symbol(a, Decl(restTuplesFromContextualTypes.ts, 76, 14)) +>b : Symbol(b, Decl(restTuplesFromContextualTypes.ts, 76, 16)) +>tuple : Symbol(tuple, Decl(restTuplesFromContextualTypes.ts, 75, 11)) // Repro from #25289 declare function take(cb: (a: number, b: string) => void): void; ->take : Symbol(take, Decl(restTuplesFromContextualTypes.ts, 61, 33)) ->cb : Symbol(cb, Decl(restTuplesFromContextualTypes.ts, 65, 22)) ->a : Symbol(a, Decl(restTuplesFromContextualTypes.ts, 65, 27)) ->b : Symbol(b, Decl(restTuplesFromContextualTypes.ts, 65, 37)) +>take : Symbol(take, Decl(restTuplesFromContextualTypes.ts, 76, 33)) +>cb : Symbol(cb, Decl(restTuplesFromContextualTypes.ts, 80, 22)) +>a : Symbol(a, Decl(restTuplesFromContextualTypes.ts, 80, 27)) +>b : Symbol(b, Decl(restTuplesFromContextualTypes.ts, 80, 37)) (function foo(...rest){}(1, '')); ->foo : Symbol(foo, Decl(restTuplesFromContextualTypes.ts, 67, 1)) ->rest : Symbol(rest, Decl(restTuplesFromContextualTypes.ts, 67, 14)) +>foo : Symbol(foo, Decl(restTuplesFromContextualTypes.ts, 82, 1)) +>rest : Symbol(rest, Decl(restTuplesFromContextualTypes.ts, 82, 14)) take(function(...rest){}); ->take : Symbol(take, Decl(restTuplesFromContextualTypes.ts, 61, 33)) ->rest : Symbol(rest, Decl(restTuplesFromContextualTypes.ts, 68, 14)) +>take : Symbol(take, Decl(restTuplesFromContextualTypes.ts, 76, 33)) +>rest : Symbol(rest, Decl(restTuplesFromContextualTypes.ts, 83, 14)) // Repro from #29833 type ArgsUnion = [number, string] | [number, Error]; ->ArgsUnion : Symbol(ArgsUnion, Decl(restTuplesFromContextualTypes.ts, 68, 26)) +>ArgsUnion : Symbol(ArgsUnion, Decl(restTuplesFromContextualTypes.ts, 83, 26)) >Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) type TupleUnionFunc = (...params: ArgsUnion) => number; ->TupleUnionFunc : Symbol(TupleUnionFunc, Decl(restTuplesFromContextualTypes.ts, 72, 52)) ->params : Symbol(params, Decl(restTuplesFromContextualTypes.ts, 73, 23)) ->ArgsUnion : Symbol(ArgsUnion, Decl(restTuplesFromContextualTypes.ts, 68, 26)) +>TupleUnionFunc : Symbol(TupleUnionFunc, Decl(restTuplesFromContextualTypes.ts, 87, 52)) +>params : Symbol(params, Decl(restTuplesFromContextualTypes.ts, 88, 23)) +>ArgsUnion : Symbol(ArgsUnion, Decl(restTuplesFromContextualTypes.ts, 83, 26)) const funcUnionTupleNoRest: TupleUnionFunc = (num, strOrErr) => { ->funcUnionTupleNoRest : Symbol(funcUnionTupleNoRest, Decl(restTuplesFromContextualTypes.ts, 75, 5)) ->TupleUnionFunc : Symbol(TupleUnionFunc, Decl(restTuplesFromContextualTypes.ts, 72, 52)) ->num : Symbol(num, Decl(restTuplesFromContextualTypes.ts, 75, 46)) ->strOrErr : Symbol(strOrErr, Decl(restTuplesFromContextualTypes.ts, 75, 50)) +>funcUnionTupleNoRest : Symbol(funcUnionTupleNoRest, Decl(restTuplesFromContextualTypes.ts, 90, 5)) +>TupleUnionFunc : Symbol(TupleUnionFunc, Decl(restTuplesFromContextualTypes.ts, 87, 52)) +>num : Symbol(num, Decl(restTuplesFromContextualTypes.ts, 90, 46)) +>strOrErr : Symbol(strOrErr, Decl(restTuplesFromContextualTypes.ts, 90, 50)) return num; ->num : Symbol(num, Decl(restTuplesFromContextualTypes.ts, 75, 46)) +>num : Symbol(num, Decl(restTuplesFromContextualTypes.ts, 90, 46)) }; const funcUnionTupleRest: TupleUnionFunc = (...params) => { ->funcUnionTupleRest : Symbol(funcUnionTupleRest, Decl(restTuplesFromContextualTypes.ts, 79, 5)) ->TupleUnionFunc : Symbol(TupleUnionFunc, Decl(restTuplesFromContextualTypes.ts, 72, 52)) ->params : Symbol(params, Decl(restTuplesFromContextualTypes.ts, 79, 44)) +>funcUnionTupleRest : Symbol(funcUnionTupleRest, Decl(restTuplesFromContextualTypes.ts, 94, 5)) +>TupleUnionFunc : Symbol(TupleUnionFunc, Decl(restTuplesFromContextualTypes.ts, 87, 52)) +>params : Symbol(params, Decl(restTuplesFromContextualTypes.ts, 94, 44)) const [num, strOrErr] = params; ->num : Symbol(num, Decl(restTuplesFromContextualTypes.ts, 80, 9)) ->strOrErr : Symbol(strOrErr, Decl(restTuplesFromContextualTypes.ts, 80, 13)) ->params : Symbol(params, Decl(restTuplesFromContextualTypes.ts, 79, 44)) +>num : Symbol(num, Decl(restTuplesFromContextualTypes.ts, 95, 9)) +>strOrErr : Symbol(strOrErr, Decl(restTuplesFromContextualTypes.ts, 95, 13)) +>params : Symbol(params, Decl(restTuplesFromContextualTypes.ts, 94, 44)) return num; ->num : Symbol(num, Decl(restTuplesFromContextualTypes.ts, 80, 9)) +>num : Symbol(num, Decl(restTuplesFromContextualTypes.ts, 95, 9)) }; diff --git a/tests/baselines/reference/restTuplesFromContextualTypes.types b/tests/baselines/reference/restTuplesFromContextualTypes.types index c282dbbae311e..6dd2a6d90cb68 100644 --- a/tests/baselines/reference/restTuplesFromContextualTypes.types +++ b/tests/baselines/reference/restTuplesFromContextualTypes.types @@ -351,6 +351,115 @@ function f4(t: T) { >x : T[number][] } +declare function f5(f: (...args: T) => U): (...args: T) => U; +>f5 : (f: (...args: T) => U) => (...args: T) => U +>f : (...args: T) => U +>args : T +>args : T + +let g0 = f5(() => "hello"); +>g0 : () => string +>f5(() => "hello") : () => string +>f5 : (f: (...args: T) => U) => (...args: T) => U +>() => "hello" : () => string +>"hello" : "hello" + +let g1 = f5((x, y) => 42); +>g1 : (x: any, y: any) => number +>f5((x, y) => 42) : (x: any, y: any) => number +>f5 : (f: (...args: T) => U) => (...args: T) => U +>(x, y) => 42 : (x: any, y: any) => number +>x : any +>y : any +>42 : 42 + +let g2 = f5((x: number, y) => 42); +>g2 : (x: number, y: any) => number +>f5((x: number, y) => 42) : (x: number, y: any) => number +>f5 : (f: (...args: T) => U) => (...args: T) => U +>(x: number, y) => 42 : (x: number, y: any) => number +>x : number +>y : any +>42 : 42 + +let g3 = f5((x: number, y: number) => x + y); +>g3 : (x: number, y: number) => number +>f5((x: number, y: number) => x + y) : (x: number, y: number) => number +>f5 : (f: (...args: T) => U) => (...args: T) => U +>(x: number, y: number) => x + y : (x: number, y: number) => number +>x : number +>y : number +>x + y : number +>x : number +>y : number + +let g4 = f5((...args) => true); +>g4 : (...args: any[]) => boolean +>f5((...args) => true) : (...args: any[]) => boolean +>f5 : (f: (...args: T) => U) => (...args: T) => U +>(...args) => true : (...args: any[]) => boolean +>args : any[] +>true : true + +declare function pipe(f: (...args: A) => B, g: (x: B) => C): (...args: A) => C; +>pipe : (f: (...args: A) => B, g: (x: B) => C) => (...args: A) => C +>f : (...args: A) => B +>args : A +>g : (x: B) => C +>x : B +>args : A + +let g5 = pipe(() => true, b => 42); +>g5 : () => number +>pipe(() => true, b => 42) : () => number +>pipe : (f: (...args: A) => B, g: (x: B) => C) => (...args: A) => C +>() => true : () => boolean +>true : true +>b => 42 : (b: boolean) => number +>b : boolean +>42 : 42 + +let g6 = pipe(x => "hello", s => s.length); +>g6 : (x: any) => number +>pipe(x => "hello", s => s.length) : (x: any) => number +>pipe : (f: (...args: A) => B, g: (x: B) => C) => (...args: A) => C +>x => "hello" : (x: any) => string +>x : any +>"hello" : "hello" +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number + +let g7 = pipe((x, y) => 42, x => "" + x); +>g7 : (x: any, y: any) => string +>pipe((x, y) => 42, x => "" + x) : (x: any, y: any) => string +>pipe : (f: (...args: A) => B, g: (x: B) => C) => (...args: A) => C +>(x, y) => 42 : (x: any, y: any) => number +>x : any +>y : any +>42 : 42 +>x => "" + x : (x: number) => string +>x : number +>"" + x : string +>"" : "" +>x : number + +let g8 = pipe((x: number, y: string) => 42, x => "" + x); +>g8 : (x: number, y: string) => string +>pipe((x: number, y: string) => 42, x => "" + x) : (x: number, y: string) => string +>pipe : (f: (...args: A) => B, g: (x: B) => C) => (...args: A) => C +>(x: number, y: string) => 42 : (x: number, y: string) => number +>x : number +>y : string +>42 : 42 +>x => "" + x : (x: number) => string +>x : number +>"" + x : string +>"" : "" +>x : number + // Repro from #25288 declare var tuple: [number, string];