=== tests/cases/conformance/types/typeRelationships/typeInference/contextualSignatureInstantiation.ts === // TypeScript Spec, section 4.12.2: // If e is an expression of a function type that contains exactly one generic call signature and no other members, // and T is a function type with exactly one non - generic call signature and no other members, then any inferences // made for type parameters referenced by the parameters of T's call signature are fixed, and e's type is changed // to a function type with e's call signature instantiated in the context of T's call signature (section 3.8.5). declare function foo(cb: (x: number, y: string) => T): T; >foo : (cb: (x: number, y: string) => T) => T >T : T >cb : (x: number, y: string) => T >x : number >y : string >T : T >T : T declare function bar(x: T, y: U, cb: (x: T, y: U) => V): V; >bar : (x: T, y: U, cb: (x: T, y: U) => V) => V >T : T >U : U >V : V >x : T >T : T >y : U >U : U >cb : (x: T, y: U) => V >x : T >T : T >y : U >U : U >V : V >V : V declare function baz(x: T, y: T, cb: (x: T, y: T) => U): U; >baz : (x: T, y: T, cb: (x: T, y: T) => U) => U >T : T >U : U >x : T >T : T >y : T >T : T >cb : (x: T, y: T) => U >x : T >T : T >y : T >T : T >U : U >U : U declare function g(x: T, y: T): T; >g : (x: T, y: T) => T >T : T >x : T >T : T >y : T >T : T >T : T declare function h(x: T, y: U): T[] | U[]; >h : (x: T, y: U) => T[] | U[] >T : T >U : U >x : T >T : T >y : U >U : U >T : T >U : U var a: number; >a : number var a = bar(1, 1, g); // Should be number >a : number >bar(1, 1, g) : number >bar : (x: T, y: U, cb: (x: T, y: U) => V) => V >1 : number >1 : number >g : (x: T, y: T) => T var a = baz(1, 1, g); // Should be number >a : number >baz(1, 1, g) : number >baz : (x: T, y: T, cb: (x: T, y: T) => U) => U >1 : number >1 : number >g : (x: T, y: T) => T var b: number | string; >b : string | number var b = foo(g); // Should be number | string >b : string | number >foo(g) : string | number >foo : (cb: (x: number, y: string) => T) => T >g : (x: T, y: T) => T var b = bar(1, "one", g); // Should be number | string >b : string | number >bar(1, "one", g) : string | number >bar : (x: T, y: U, cb: (x: T, y: U) => V) => V >1 : number >"one" : string >g : (x: T, y: T) => T var b = bar("one", 1, g); // Should be number | string >b : string | number >bar("one", 1, g) : string | number >bar : (x: T, y: U, cb: (x: T, y: U) => V) => V >"one" : string >1 : number >g : (x: T, y: T) => T var b = baz(b, b, g); // Should be number | string >b : string | number >baz(b, b, g) : string | number >baz : (x: T, y: T, cb: (x: T, y: T) => U) => U >b : string | number >b : string | number >g : (x: T, y: T) => T var d: number[] | string[]; >d : string[] | number[] var d = foo(h); // Should be number[] | string[] >d : string[] | number[] >foo(h) : string[] | number[] >foo : (cb: (x: number, y: string) => T) => T >h : (x: T, y: U) => T[] | U[] var d = bar(1, "one", h); // Should be number[] | string[] >d : string[] | number[] >bar(1, "one", h) : string[] | number[] >bar : (x: T, y: U, cb: (x: T, y: U) => V) => V >1 : number >"one" : string >h : (x: T, y: U) => T[] | U[] var d = bar("one", 1, h); // Should be number[] | string[] >d : string[] | number[] >bar("one", 1, h) : string[] | number[] >bar : (x: T, y: U, cb: (x: T, y: U) => V) => V >"one" : string >1 : number >h : (x: T, y: U) => T[] | U[] var d = baz(d, d, g); // Should be number[] | string[] >d : string[] | number[] >baz(d, d, g) : string[] | number[] >baz : (x: T, y: T, cb: (x: T, y: T) => U) => U >d : string[] | number[] >d : string[] | number[] >g : (x: T, y: T) => T