Improve inference for context sensitive functions in object and array literal arguments (#48538)

* Use intra-expression inference sites in type argument inference

* Accept new baselines

* Add tests
This commit is contained in:
Anders Hejlsberg
2022-04-05 13:08:59 -07:00
committed by GitHub
parent 7da80d79e2
commit a3c22187c9
8 changed files with 1968 additions and 43 deletions

View File

@@ -21749,6 +21749,9 @@ namespace ts {
const inference = inferences[i];
if (t === inference.typeParameter) {
if (fix && !inference.isFixed) {
// Before we commit to a particular inference (and thus lock out any further inferences),
// we infer from any intra-expression inference sites we have collected.
inferFromIntraExpressionSites(context);
clearCachedInferences(inferences);
inference.isFixed = true;
}
@@ -21766,6 +21769,37 @@ namespace ts {
}
}
function addIntraExpressionInferenceSite(context: InferenceContext, node: Expression | MethodDeclaration, type: Type) {
(context.intraExpressionInferenceSites ??= []).push({ node, type });
}
// We collect intra-expression inference sites within object and array literals to handle cases where
// inferred types flow between context sensitive element expressions. For example:
//
// declare function foo<T>(arg: [(n: number) => T, (x: T) => void]): void;
// foo([_a => 0, n => n.toFixed()]);
//
// Above, both arrow functions in the tuple argument are context sensitive, thus both are omitted from the
// pass that collects inferences from the non-context sensitive parts of the arguments. In the subsequent
// pass where nothing is omitted, we need to commit to an inference for T in order to contextually type the
// parameter in the second arrow function, but we want to first infer from the return type of the first
// arrow function. This happens automatically when the arrow functions are discrete arguments (because we
// infer from each argument before processing the next), but when the arrow functions are elements of an
// object or array literal, we need to perform intra-expression inferences early.
function inferFromIntraExpressionSites(context: InferenceContext) {
if (context.intraExpressionInferenceSites) {
for (const { node, type } of context.intraExpressionInferenceSites) {
const contextualType = node.kind === SyntaxKind.MethodDeclaration ?
getContextualTypeForObjectLiteralMethod(node as MethodDeclaration, ContextFlags.NoConstraints) :
getContextualType(node, ContextFlags.NoConstraints);
if (contextualType) {
inferTypes(context.inferences, type, contextualType);
}
}
context.intraExpressionInferenceSites = undefined;
}
}
function createInferenceInfo(typeParameter: TypeParameter): InferenceInfo {
return {
typeParameter,
@@ -27429,6 +27463,11 @@ namespace ts {
const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType, forceTuple);
elementTypes.push(addOptionality(type, /*isProperty*/ true, hasOmittedExpression));
elementFlags.push(hasOmittedExpression ? ElementFlags.Optional : ElementFlags.Required);
if (contextualType && someType(contextualType, isTupleLikeType) && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(e)) {
const inferenceContext = getInferenceContext(node);
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
addIntraExpressionInferenceSite(inferenceContext, e, type);
}
}
}
if (inDestructuringPattern) {
@@ -27646,6 +27685,14 @@ namespace ts {
prop.target = member;
member = prop;
allPropertiesTable?.set(prop.escapedName, prop);
if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) &&
(memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && isContextSensitive(memberDecl)) {
const inferenceContext = getInferenceContext(node);
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
const inferenceNode = memberDecl.kind === SyntaxKind.PropertyAssignment ? memberDecl.initializer : memberDecl;
addIntraExpressionInferenceSite(inferenceContext, inferenceNode, type);
}
}
else if (memberDecl.kind === SyntaxKind.SpreadAssignment) {
if (languageVersion < ScriptTarget.ES2015) {
@@ -29748,34 +29795,36 @@ namespace ts {
if (node.kind !== SyntaxKind.Decorator) {
const contextualType = getContextualType(node, every(signature.typeParameters, p => !!getDefaultFromTypeParameter(p)) ? ContextFlags.SkipBindingPatterns : ContextFlags.None);
if (contextualType) {
// We clone the inference context 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 outerContext = getInferenceContext(node);
const outerMapper = getMapperFromContext(cloneInferenceContext(outerContext, InferenceFlags.NoDefault));
const instantiatedType = instantiateType(contextualType, outerMapper);
// 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
// be inferred as actual types from the contextual type. For example:
// declare function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[];
// const boxElements: <A>(a: A[]) => { value: A }[] = arrayMap(value => ({ value }));
// Above, the type of the 'value' parameter is inferred to be 'A'.
const contextualSignature = getSingleCallSignature(instantiatedType);
const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ?
getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters)) :
instantiatedType;
const inferenceTargetType = getReturnTypeOfSignature(signature);
// Inferences made from return types have lower priority than all other inferences.
inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType);
// Create a type mapper for instantiating generic contextual types using the inferences made
// from the return type. We need a separate inference pass here because (a) instantiation of
// the source type uses the outer context's return mapper (which excludes inferences made from
// outer arguments), and (b) we don't want any further inferences going into this context.
const returnContext = createInferenceContext(signature.typeParameters!, signature, context.flags);
const returnSourceType = instantiateType(contextualType, outerContext && outerContext.returnMapper);
inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType);
context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined;
if (couldContainTypeVariables(inferenceTargetType)) {
// We clone the inference context 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 outerContext = getInferenceContext(node);
const outerMapper = getMapperFromContext(cloneInferenceContext(outerContext, InferenceFlags.NoDefault));
const instantiatedType = instantiateType(contextualType, outerMapper);
// 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
// be inferred as actual types from the contextual type. For example:
// declare function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[];
// const boxElements: <A>(a: A[]) => { value: A }[] = arrayMap(value => ({ value }));
// Above, the type of the 'value' parameter is inferred to be 'A'.
const contextualSignature = getSingleCallSignature(instantiatedType);
const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ?
getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters)) :
instantiatedType;
// Inferences made from return types have lower priority than all other inferences.
inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType);
// Create a type mapper for instantiating generic contextual types using the inferences made
// from the return type. We need a separate inference pass here because (a) instantiation of
// the source type uses the outer context's return mapper (which excludes inferences made from
// outer arguments), and (b) we don't want any further inferences going into this context.
const returnContext = createInferenceContext(signature.typeParameters!, signature, context.flags);
const returnSourceType = instantiateType(contextualType, outerContext && outerContext.returnMapper);
inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType);
context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined;
}
}
}
@@ -29789,7 +29838,7 @@ namespace ts {
}
const thisType = getThisTypeOfSignature(signature);
if (thisType) {
if (thisType && couldContainTypeVariables(thisType)) {
const thisArgumentNode = getThisArgumentOfCall(node);
inferTypes(context.inferences, getThisArgumentType(thisArgumentNode), thisType);
}
@@ -29798,12 +29847,14 @@ namespace ts {
const arg = args[i];
if (arg.kind !== SyntaxKind.OmittedExpression && !(checkMode & CheckMode.IsForStringLiteralArgumentCompletions && hasSkipDirectInferenceFlag(arg))) {
const paramType = getTypeAtPosition(signature, i);
const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode);
inferTypes(context.inferences, argType, paramType);
if (couldContainTypeVariables(paramType)) {
const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode);
inferTypes(context.inferences, argType, paramType);
}
}
}
if (restType) {
if (restType && couldContainTypeVariables(restType)) {
const spreadType = getSpreadArgumentType(args, argCount, args.length, restType, context, checkMode);
inferTypes(context.inferences, spreadType, restType);
}
@@ -34162,6 +34213,11 @@ namespace ts {
context.contextualType = contextualType;
context.inferenceContext = inferenceContext;
const type = checkExpression(node, checkMode | CheckMode.Contextual | (inferenceContext ? CheckMode.Inferential : 0));
// In CheckMode.Inferential we collect intra-expression inference sites to process before fixing any type
// parameters. This information is no longer needed after the call to checkExpression.
if (inferenceContext && inferenceContext.intraExpressionInferenceSites) {
inferenceContext.intraExpressionInferenceSites = undefined;
}
// We strip literal freshness when an appropriate contextual type is present such that contextually typed
// literals always preserve their literal types (otherwise they might widen during type inference). An alternative
// here would be to not mark contextually typed literals as fresh in the first place.

View File

@@ -5915,6 +5915,13 @@ namespace ts {
nonFixingMapper: TypeMapper; // Mapper that doesn't fix inferences
returnMapper?: TypeMapper; // Type mapper for inferences from return types (if any)
inferredTypeParameters?: readonly TypeParameter[]; // Inferred type parameters for function result
intraExpressionInferenceSites?: IntraExpressionInferenceSite[];
}
/* @internal */
export interface IntraExpressionInferenceSite {
node: Expression | MethodDeclaration;
type: Type;
}
/* @internal */

View File

@@ -25,7 +25,7 @@ declare function app<State, Actions extends ActionsObject<State>>(obj: Options<S
app({
>app({ state: 100, actions: { foo: s => s // Should be typed number => number }, view: (s, a) => undefined as any,}) : void
>app : <State, Actions extends ActionsObject<State>>(obj: Options<State, Actions>) => void
>{ state: 100, actions: { foo: s => s // Should be typed number => number }, view: (s, a) => undefined as any,} : { state: number; actions: { foo: (s: number) => number; }; view: (s: number, a: ActionsObject<number>) => any; }
>{ state: 100, actions: { foo: s => s // Should be typed number => number }, view: (s, a) => undefined as any,} : { state: number; actions: { foo: (s: number) => number; }; view: (s: number, a: { foo: (s: number) => number; }) => any; }
state: 100,
>state : number
@@ -43,10 +43,10 @@ app({
},
view: (s, a) => undefined as any,
>view : (s: number, a: ActionsObject<number>) => any
>(s, a) => undefined as any : (s: number, a: ActionsObject<number>) => any
>view : (s: number, a: { foo: (s: number) => number; }) => any
>(s, a) => undefined as any : (s: number, a: { foo: (s: number) => number; }) => any
>s : number
>a : ActionsObject<number>
>a : { foo: (s: number) => number; }
>undefined as any : any
>undefined : undefined
@@ -95,7 +95,7 @@ declare function app2<State, Actions extends ActionsObject<State>>(obj: Options2
app2({
>app2({ state: 100, actions: { foo: s => s // Should be typed number => number }, view: (s, a) => undefined as any,}) : void
>app2 : <State, Actions extends ActionsObject<State>>(obj: Options2<State, Actions>) => void
>{ state: 100, actions: { foo: s => s // Should be typed number => number }, view: (s, a) => undefined as any,} : { state: number; actions: { foo: (s: number) => number; }; view: (s: number, a: ActionsObject<number>) => any; }
>{ state: 100, actions: { foo: s => s // Should be typed number => number }, view: (s, a) => undefined as any,} : { state: number; actions: { foo: (s: number) => number; }; view: (s: number, a: { foo: (s: number) => number; }) => any; }
state: 100,
>state : number
@@ -113,10 +113,10 @@ app2({
},
view: (s, a) => undefined as any,
>view : (s: number, a: ActionsObject<number>) => any
>(s, a) => undefined as any : (s: number, a: ActionsObject<number>) => any
>view : (s: number, a: { foo: (s: number) => number; }) => any
>(s, a) => undefined as any : (s: number, a: { foo: (s: number) => number; }) => any
>s : number
>a : ActionsObject<number>
>a : { foo: (s: number) => number; }
>undefined as any : any
>undefined : undefined
@@ -134,7 +134,7 @@ declare function app3<State, Actions extends ActionsArray<State>>(obj: Options<S
app3({
>app3({ state: 100, actions: [ s => s // Should be typed number => number ], view: (s, a) => undefined as any,}) : void
>app3 : <State, Actions extends ActionsArray<State>>(obj: Options<State, Actions>) => void
>{ state: 100, actions: [ s => s // Should be typed number => number ], view: (s, a) => undefined as any,} : { state: number; actions: ((s: number) => number)[]; view: (s: number, a: ActionsArray<number>) => any; }
>{ state: 100, actions: [ s => s // Should be typed number => number ], view: (s, a) => undefined as any,} : { state: number; actions: ((s: number) => number)[]; view: (s: number, a: ((s: number) => number)[]) => any; }
state: 100,
>state : number
@@ -151,10 +151,10 @@ app3({
],
view: (s, a) => undefined as any,
>view : (s: number, a: ActionsArray<number>) => any
>(s, a) => undefined as any : (s: number, a: ActionsArray<number>) => any
>view : (s: number, a: ((s: number) => number)[]) => any
>(s, a) => undefined as any : (s: number, a: ((s: number) => number)[]) => any
>s : number
>a : ActionsArray<number>
>a : ((s: number) => number)[]
>undefined as any : any
>undefined : undefined

View File

@@ -0,0 +1,192 @@
tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts(123,5): error TS2322: Type '(inputs: Unwrap<{ num: Wrapper<number>; str: Wrapper<string>; }>) => { bool: any; str: number; }' is not assignable to type '(inputs: Unwrap<{ num: Wrapper<number>; str: Wrapper<string>; }>) => Unwrap<{ bool: Wrapper<boolean>; str: Wrapper<string>; }>'.
Call signature return types '{ bool: any; str: number; }' and 'Unwrap<{ bool: Wrapper<boolean>; str: Wrapper<string>; }>' are incompatible.
The types of 'str' are incompatible between these types.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts(125,26): error TS2339: Property 'nonexistent' does not exist on type 'Unwrap<{ num: Wrapper<number>; str: Wrapper<string>; }>'.
==== tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts (2 errors) ====
// Repros from #47599
declare function callIt<T>(obj: {
produce: (n: number) => T,
consume: (x: T) => void
}): void;
callIt({
produce: () => 0,
consume: n => n.toFixed()
});
callIt({
produce: _a => 0,
consume: n => n.toFixed(),
});
callIt({
produce() {
return 0;
},
consume: n => n.toFixed()
});
declare function callItT<T>(obj: [(n: number) => T, (x: T) => void]): void;
callItT([() => 0, n => n.toFixed()]);
callItT([_a => 0, n => n.toFixed()]);
// Repro from #25092
interface MyInterface<T> {
retrieveGeneric: (parameter: string) => T,
operateWithGeneric: (generic: T) => string
}
const inferTypeFn = <T>(generic: MyInterface<T>) => generic;
const myGeneric = inferTypeFn({
retrieveGeneric: parameter => 5,
operateWithGeneric: generic => generic.toFixed()
});
// Repro #38623
function make<M>(o: { mutations: M, action: (m: M) => void }) { }
make({
mutations: {
foo() { }
},
action: (a) => { a.foo() }
});
// Repro from #38845
declare function foo<A>(options: { a: A, b: (a: A) => void }): void;
foo({
a: () => { return 42 },
b(a) {},
});
foo({
a: function () { return 42 },
b(a) {},
});
foo({
a() { return 42 },
b(a) {},
});
// Repro from #38872
type Chain<R1, R2> = {
a(): R1,
b(a: R1): R2;
c(b: R2): void;
};
function test<R1, R2>(foo: Chain<R1, R2>) {}
test({
a: () => 0,
b: (a) => 'a',
c: (b) => {
const x: string = b;
}
});
// Repro from #41712
class Wrapper<T = any> {
public value?: T;
}
type WrappedMap = Record<string, Wrapper>;
type Unwrap<D extends WrappedMap> = {
[K in keyof D]: D[K] extends Wrapper<infer T> ? T : never;
};
type MappingComponent<I extends WrappedMap, O extends WrappedMap> = {
setup(): { inputs: I; outputs: O };
map?: (inputs: Unwrap<I>) => Unwrap<O>;
};
declare function createMappingComponent<I extends WrappedMap, O extends WrappedMap>(def: MappingComponent<I, O>): void;
createMappingComponent({
setup() {
return {
inputs: {
num: new Wrapper<number>(),
str: new Wrapper<string>()
},
outputs: {
bool: new Wrapper<boolean>(),
str: new Wrapper<string>()
}
};
},
map(inputs) {
~~~
!!! error TS2322: Type '(inputs: Unwrap<{ num: Wrapper<number>; str: Wrapper<string>; }>) => { bool: any; str: number; }' is not assignable to type '(inputs: Unwrap<{ num: Wrapper<number>; str: Wrapper<string>; }>) => Unwrap<{ bool: Wrapper<boolean>; str: Wrapper<string>; }>'.
!!! error TS2322: Call signature return types '{ bool: any; str: number; }' and 'Unwrap<{ bool: Wrapper<boolean>; str: Wrapper<string>; }>' are incompatible.
!!! error TS2322: The types of 'str' are incompatible between these types.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
!!! related TS6500 tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts:105:5: The expected type comes from property 'map' which is declared here on type 'MappingComponent<{ num: Wrapper<number>; str: Wrapper<string>; }, { bool: Wrapper<boolean>; str: Wrapper<string>; }>'
return {
bool: inputs.nonexistent,
~~~~~~~~~~~
!!! error TS2339: Property 'nonexistent' does not exist on type 'Unwrap<{ num: Wrapper<number>; str: Wrapper<string>; }>'.
str: inputs.num, // Causes error
}
}
});
// Repro from #48279
function simplified<T>(props: { generator: () => T, receiver: (t: T) => any }) {}
function whatIWant<T>(props: { generator: (bob: any) => T, receiver: (t: T) => any }) {}
function nonObject<T>(generator: (bob: any) => T, receiver: (t: T) => any) {}
simplified({ generator: () => 123, receiver: (t) => console.log(t + 2) })
whatIWant({ generator: (bob) => bob ? 1 : 2, receiver: (t) => console.log(t + 2) })
nonObject((bob) => bob ? 1 : 2, (t) => console.log(t + 2))
// Repro from #48466
interface Opts<TParams, TDone, TMapped> {
fetch: (params: TParams, foo: number) => TDone,
map: (data: TDone) => TMapped
}
function example<TParams, TDone, TMapped>(options: Opts<TParams, TDone, TMapped>) {
return (params: TParams) => {
const data = options.fetch(params, 123)
return options.map(data)
}
}
interface Params {
one: number
two: string
}
example({
fetch: (params: Params) => 123,
map: (number) => String(number)
});
example({
fetch: (params: Params, foo: number) => 123,
map: (number) => String(number)
});
example({
fetch: (params: Params, foo) => 123,
map: (number) => String(number)
});

View File

@@ -0,0 +1,342 @@
//// [intraExpressionInferences.ts]
// Repros from #47599
declare function callIt<T>(obj: {
produce: (n: number) => T,
consume: (x: T) => void
}): void;
callIt({
produce: () => 0,
consume: n => n.toFixed()
});
callIt({
produce: _a => 0,
consume: n => n.toFixed(),
});
callIt({
produce() {
return 0;
},
consume: n => n.toFixed()
});
declare function callItT<T>(obj: [(n: number) => T, (x: T) => void]): void;
callItT([() => 0, n => n.toFixed()]);
callItT([_a => 0, n => n.toFixed()]);
// Repro from #25092
interface MyInterface<T> {
retrieveGeneric: (parameter: string) => T,
operateWithGeneric: (generic: T) => string
}
const inferTypeFn = <T>(generic: MyInterface<T>) => generic;
const myGeneric = inferTypeFn({
retrieveGeneric: parameter => 5,
operateWithGeneric: generic => generic.toFixed()
});
// Repro #38623
function make<M>(o: { mutations: M, action: (m: M) => void }) { }
make({
mutations: {
foo() { }
},
action: (a) => { a.foo() }
});
// Repro from #38845
declare function foo<A>(options: { a: A, b: (a: A) => void }): void;
foo({
a: () => { return 42 },
b(a) {},
});
foo({
a: function () { return 42 },
b(a) {},
});
foo({
a() { return 42 },
b(a) {},
});
// Repro from #38872
type Chain<R1, R2> = {
a(): R1,
b(a: R1): R2;
c(b: R2): void;
};
function test<R1, R2>(foo: Chain<R1, R2>) {}
test({
a: () => 0,
b: (a) => 'a',
c: (b) => {
const x: string = b;
}
});
// Repro from #41712
class Wrapper<T = any> {
public value?: T;
}
type WrappedMap = Record<string, Wrapper>;
type Unwrap<D extends WrappedMap> = {
[K in keyof D]: D[K] extends Wrapper<infer T> ? T : never;
};
type MappingComponent<I extends WrappedMap, O extends WrappedMap> = {
setup(): { inputs: I; outputs: O };
map?: (inputs: Unwrap<I>) => Unwrap<O>;
};
declare function createMappingComponent<I extends WrappedMap, O extends WrappedMap>(def: MappingComponent<I, O>): void;
createMappingComponent({
setup() {
return {
inputs: {
num: new Wrapper<number>(),
str: new Wrapper<string>()
},
outputs: {
bool: new Wrapper<boolean>(),
str: new Wrapper<string>()
}
};
},
map(inputs) {
return {
bool: inputs.nonexistent,
str: inputs.num, // Causes error
}
}
});
// Repro from #48279
function simplified<T>(props: { generator: () => T, receiver: (t: T) => any }) {}
function whatIWant<T>(props: { generator: (bob: any) => T, receiver: (t: T) => any }) {}
function nonObject<T>(generator: (bob: any) => T, receiver: (t: T) => any) {}
simplified({ generator: () => 123, receiver: (t) => console.log(t + 2) })
whatIWant({ generator: (bob) => bob ? 1 : 2, receiver: (t) => console.log(t + 2) })
nonObject((bob) => bob ? 1 : 2, (t) => console.log(t + 2))
// Repro from #48466
interface Opts<TParams, TDone, TMapped> {
fetch: (params: TParams, foo: number) => TDone,
map: (data: TDone) => TMapped
}
function example<TParams, TDone, TMapped>(options: Opts<TParams, TDone, TMapped>) {
return (params: TParams) => {
const data = options.fetch(params, 123)
return options.map(data)
}
}
interface Params {
one: number
two: string
}
example({
fetch: (params: Params) => 123,
map: (number) => String(number)
});
example({
fetch: (params: Params, foo: number) => 123,
map: (number) => String(number)
});
example({
fetch: (params: Params, foo) => 123,
map: (number) => String(number)
});
//// [intraExpressionInferences.js]
"use strict";
// Repros from #47599
callIt({
produce: function () { return 0; },
consume: function (n) { return n.toFixed(); }
});
callIt({
produce: function (_a) { return 0; },
consume: function (n) { return n.toFixed(); }
});
callIt({
produce: function () {
return 0;
},
consume: function (n) { return n.toFixed(); }
});
callItT([function () { return 0; }, function (n) { return n.toFixed(); }]);
callItT([function (_a) { return 0; }, function (n) { return n.toFixed(); }]);
var inferTypeFn = function (generic) { return generic; };
var myGeneric = inferTypeFn({
retrieveGeneric: function (parameter) { return 5; },
operateWithGeneric: function (generic) { return generic.toFixed(); }
});
// Repro #38623
function make(o) { }
make({
mutations: {
foo: function () { }
},
action: function (a) { a.foo(); }
});
foo({
a: function () { return 42; },
b: function (a) { }
});
foo({
a: function () { return 42; },
b: function (a) { }
});
foo({
a: function () { return 42; },
b: function (a) { }
});
function test(foo) { }
test({
a: function () { return 0; },
b: function (a) { return 'a'; },
c: function (b) {
var x = b;
}
});
// Repro from #41712
var Wrapper = /** @class */ (function () {
function Wrapper() {
}
return Wrapper;
}());
createMappingComponent({
setup: function () {
return {
inputs: {
num: new Wrapper(),
str: new Wrapper()
},
outputs: {
bool: new Wrapper(),
str: new Wrapper()
}
};
},
map: function (inputs) {
return {
bool: inputs.nonexistent,
str: inputs.num
};
}
});
// Repro from #48279
function simplified(props) { }
function whatIWant(props) { }
function nonObject(generator, receiver) { }
simplified({ generator: function () { return 123; }, receiver: function (t) { return console.log(t + 2); } });
whatIWant({ generator: function (bob) { return bob ? 1 : 2; }, receiver: function (t) { return console.log(t + 2); } });
nonObject(function (bob) { return bob ? 1 : 2; }, function (t) { return console.log(t + 2); });
function example(options) {
return function (params) {
var data = options.fetch(params, 123);
return options.map(data);
};
}
example({
fetch: function (params) { return 123; },
map: function (number) { return String(number); }
});
example({
fetch: function (params, foo) { return 123; },
map: function (number) { return String(number); }
});
example({
fetch: function (params, foo) { return 123; },
map: function (number) { return String(number); }
});
//// [intraExpressionInferences.d.ts]
declare function callIt<T>(obj: {
produce: (n: number) => T;
consume: (x: T) => void;
}): void;
declare function callItT<T>(obj: [(n: number) => T, (x: T) => void]): void;
interface MyInterface<T> {
retrieveGeneric: (parameter: string) => T;
operateWithGeneric: (generic: T) => string;
}
declare const inferTypeFn: <T>(generic: MyInterface<T>) => MyInterface<T>;
declare const myGeneric: MyInterface<number>;
declare function make<M>(o: {
mutations: M;
action: (m: M) => void;
}): void;
declare function foo<A>(options: {
a: A;
b: (a: A) => void;
}): void;
declare type Chain<R1, R2> = {
a(): R1;
b(a: R1): R2;
c(b: R2): void;
};
declare function test<R1, R2>(foo: Chain<R1, R2>): void;
declare class Wrapper<T = any> {
value?: T;
}
declare type WrappedMap = Record<string, Wrapper>;
declare type Unwrap<D extends WrappedMap> = {
[K in keyof D]: D[K] extends Wrapper<infer T> ? T : never;
};
declare type MappingComponent<I extends WrappedMap, O extends WrappedMap> = {
setup(): {
inputs: I;
outputs: O;
};
map?: (inputs: Unwrap<I>) => Unwrap<O>;
};
declare function createMappingComponent<I extends WrappedMap, O extends WrappedMap>(def: MappingComponent<I, O>): void;
declare function simplified<T>(props: {
generator: () => T;
receiver: (t: T) => any;
}): void;
declare function whatIWant<T>(props: {
generator: (bob: any) => T;
receiver: (t: T) => any;
}): void;
declare function nonObject<T>(generator: (bob: any) => T, receiver: (t: T) => any): void;
interface Opts<TParams, TDone, TMapped> {
fetch: (params: TParams, foo: number) => TDone;
map: (data: TDone) => TMapped;
}
declare function example<TParams, TDone, TMapped>(options: Opts<TParams, TDone, TMapped>): (params: TParams) => TMapped;
interface Params {
one: number;
two: string;
}

View File

@@ -0,0 +1,560 @@
=== tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts ===
// Repros from #47599
declare function callIt<T>(obj: {
>callIt : Symbol(callIt, Decl(intraExpressionInferences.ts, 0, 0))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 2, 24))
>obj : Symbol(obj, Decl(intraExpressionInferences.ts, 2, 27))
produce: (n: number) => T,
>produce : Symbol(produce, Decl(intraExpressionInferences.ts, 2, 33))
>n : Symbol(n, Decl(intraExpressionInferences.ts, 3, 14))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 2, 24))
consume: (x: T) => void
>consume : Symbol(consume, Decl(intraExpressionInferences.ts, 3, 30))
>x : Symbol(x, Decl(intraExpressionInferences.ts, 4, 14))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 2, 24))
}): void;
callIt({
>callIt : Symbol(callIt, Decl(intraExpressionInferences.ts, 0, 0))
produce: () => 0,
>produce : Symbol(produce, Decl(intraExpressionInferences.ts, 7, 8))
consume: n => n.toFixed()
>consume : Symbol(consume, Decl(intraExpressionInferences.ts, 8, 21))
>n : Symbol(n, Decl(intraExpressionInferences.ts, 9, 12))
>n.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
>n : Symbol(n, Decl(intraExpressionInferences.ts, 9, 12))
>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
});
callIt({
>callIt : Symbol(callIt, Decl(intraExpressionInferences.ts, 0, 0))
produce: _a => 0,
>produce : Symbol(produce, Decl(intraExpressionInferences.ts, 12, 8))
>_a : Symbol(_a, Decl(intraExpressionInferences.ts, 13, 12))
consume: n => n.toFixed(),
>consume : Symbol(consume, Decl(intraExpressionInferences.ts, 13, 21))
>n : Symbol(n, Decl(intraExpressionInferences.ts, 14, 12))
>n.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
>n : Symbol(n, Decl(intraExpressionInferences.ts, 14, 12))
>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
});
callIt({
>callIt : Symbol(callIt, Decl(intraExpressionInferences.ts, 0, 0))
produce() {
>produce : Symbol(produce, Decl(intraExpressionInferences.ts, 17, 8))
return 0;
},
consume: n => n.toFixed()
>consume : Symbol(consume, Decl(intraExpressionInferences.ts, 20, 6))
>n : Symbol(n, Decl(intraExpressionInferences.ts, 21, 12))
>n.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
>n : Symbol(n, Decl(intraExpressionInferences.ts, 21, 12))
>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
});
declare function callItT<T>(obj: [(n: number) => T, (x: T) => void]): void;
>callItT : Symbol(callItT, Decl(intraExpressionInferences.ts, 22, 3))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 24, 25))
>obj : Symbol(obj, Decl(intraExpressionInferences.ts, 24, 28))
>n : Symbol(n, Decl(intraExpressionInferences.ts, 24, 35))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 24, 25))
>x : Symbol(x, Decl(intraExpressionInferences.ts, 24, 53))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 24, 25))
callItT([() => 0, n => n.toFixed()]);
>callItT : Symbol(callItT, Decl(intraExpressionInferences.ts, 22, 3))
>n : Symbol(n, Decl(intraExpressionInferences.ts, 26, 17))
>n.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
>n : Symbol(n, Decl(intraExpressionInferences.ts, 26, 17))
>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
callItT([_a => 0, n => n.toFixed()]);
>callItT : Symbol(callItT, Decl(intraExpressionInferences.ts, 22, 3))
>_a : Symbol(_a, Decl(intraExpressionInferences.ts, 27, 9))
>n : Symbol(n, Decl(intraExpressionInferences.ts, 27, 17))
>n.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
>n : Symbol(n, Decl(intraExpressionInferences.ts, 27, 17))
>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
// Repro from #25092
interface MyInterface<T> {
>MyInterface : Symbol(MyInterface, Decl(intraExpressionInferences.ts, 27, 37))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 31, 22))
retrieveGeneric: (parameter: string) => T,
>retrieveGeneric : Symbol(MyInterface.retrieveGeneric, Decl(intraExpressionInferences.ts, 31, 26))
>parameter : Symbol(parameter, Decl(intraExpressionInferences.ts, 32, 22))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 31, 22))
operateWithGeneric: (generic: T) => string
>operateWithGeneric : Symbol(MyInterface.operateWithGeneric, Decl(intraExpressionInferences.ts, 32, 46))
>generic : Symbol(generic, Decl(intraExpressionInferences.ts, 33, 25))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 31, 22))
}
const inferTypeFn = <T>(generic: MyInterface<T>) => generic;
>inferTypeFn : Symbol(inferTypeFn, Decl(intraExpressionInferences.ts, 36, 5))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 36, 21))
>generic : Symbol(generic, Decl(intraExpressionInferences.ts, 36, 24))
>MyInterface : Symbol(MyInterface, Decl(intraExpressionInferences.ts, 27, 37))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 36, 21))
>generic : Symbol(generic, Decl(intraExpressionInferences.ts, 36, 24))
const myGeneric = inferTypeFn({
>myGeneric : Symbol(myGeneric, Decl(intraExpressionInferences.ts, 38, 5))
>inferTypeFn : Symbol(inferTypeFn, Decl(intraExpressionInferences.ts, 36, 5))
retrieveGeneric: parameter => 5,
>retrieveGeneric : Symbol(retrieveGeneric, Decl(intraExpressionInferences.ts, 38, 31))
>parameter : Symbol(parameter, Decl(intraExpressionInferences.ts, 39, 20))
operateWithGeneric: generic => generic.toFixed()
>operateWithGeneric : Symbol(operateWithGeneric, Decl(intraExpressionInferences.ts, 39, 36))
>generic : Symbol(generic, Decl(intraExpressionInferences.ts, 40, 23))
>generic.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
>generic : Symbol(generic, Decl(intraExpressionInferences.ts, 40, 23))
>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
});
// Repro #38623
function make<M>(o: { mutations: M, action: (m: M) => void }) { }
>make : Symbol(make, Decl(intraExpressionInferences.ts, 41, 3))
>M : Symbol(M, Decl(intraExpressionInferences.ts, 45, 14))
>o : Symbol(o, Decl(intraExpressionInferences.ts, 45, 17))
>mutations : Symbol(mutations, Decl(intraExpressionInferences.ts, 45, 21))
>M : Symbol(M, Decl(intraExpressionInferences.ts, 45, 14))
>action : Symbol(action, Decl(intraExpressionInferences.ts, 45, 35))
>m : Symbol(m, Decl(intraExpressionInferences.ts, 45, 46))
>M : Symbol(M, Decl(intraExpressionInferences.ts, 45, 14))
make({
>make : Symbol(make, Decl(intraExpressionInferences.ts, 41, 3))
mutations: {
>mutations : Symbol(mutations, Decl(intraExpressionInferences.ts, 47, 6))
foo() { }
>foo : Symbol(foo, Decl(intraExpressionInferences.ts, 48, 15))
},
action: (a) => { a.foo() }
>action : Symbol(action, Decl(intraExpressionInferences.ts, 50, 5))
>a : Symbol(a, Decl(intraExpressionInferences.ts, 51, 12))
>a.foo : Symbol(foo, Decl(intraExpressionInferences.ts, 48, 15))
>a : Symbol(a, Decl(intraExpressionInferences.ts, 51, 12))
>foo : Symbol(foo, Decl(intraExpressionInferences.ts, 48, 15))
});
// Repro from #38845
declare function foo<A>(options: { a: A, b: (a: A) => void }): void;
>foo : Symbol(foo, Decl(intraExpressionInferences.ts, 52, 3))
>A : Symbol(A, Decl(intraExpressionInferences.ts, 56, 21))
>options : Symbol(options, Decl(intraExpressionInferences.ts, 56, 24))
>a : Symbol(a, Decl(intraExpressionInferences.ts, 56, 34))
>A : Symbol(A, Decl(intraExpressionInferences.ts, 56, 21))
>b : Symbol(b, Decl(intraExpressionInferences.ts, 56, 40))
>a : Symbol(a, Decl(intraExpressionInferences.ts, 56, 45))
>A : Symbol(A, Decl(intraExpressionInferences.ts, 56, 21))
foo({
>foo : Symbol(foo, Decl(intraExpressionInferences.ts, 52, 3))
a: () => { return 42 },
>a : Symbol(a, Decl(intraExpressionInferences.ts, 58, 5))
b(a) {},
>b : Symbol(b, Decl(intraExpressionInferences.ts, 59, 27))
>a : Symbol(a, Decl(intraExpressionInferences.ts, 60, 6))
});
foo({
>foo : Symbol(foo, Decl(intraExpressionInferences.ts, 52, 3))
a: function () { return 42 },
>a : Symbol(a, Decl(intraExpressionInferences.ts, 63, 5))
b(a) {},
>b : Symbol(b, Decl(intraExpressionInferences.ts, 64, 33))
>a : Symbol(a, Decl(intraExpressionInferences.ts, 65, 6))
});
foo({
>foo : Symbol(foo, Decl(intraExpressionInferences.ts, 52, 3))
a() { return 42 },
>a : Symbol(a, Decl(intraExpressionInferences.ts, 68, 5))
b(a) {},
>b : Symbol(b, Decl(intraExpressionInferences.ts, 69, 22))
>a : Symbol(a, Decl(intraExpressionInferences.ts, 70, 6))
});
// Repro from #38872
type Chain<R1, R2> = {
>Chain : Symbol(Chain, Decl(intraExpressionInferences.ts, 71, 3))
>R1 : Symbol(R1, Decl(intraExpressionInferences.ts, 75, 11))
>R2 : Symbol(R2, Decl(intraExpressionInferences.ts, 75, 14))
a(): R1,
>a : Symbol(a, Decl(intraExpressionInferences.ts, 75, 22))
>R1 : Symbol(R1, Decl(intraExpressionInferences.ts, 75, 11))
b(a: R1): R2;
>b : Symbol(b, Decl(intraExpressionInferences.ts, 76, 12))
>a : Symbol(a, Decl(intraExpressionInferences.ts, 77, 6))
>R1 : Symbol(R1, Decl(intraExpressionInferences.ts, 75, 11))
>R2 : Symbol(R2, Decl(intraExpressionInferences.ts, 75, 14))
c(b: R2): void;
>c : Symbol(c, Decl(intraExpressionInferences.ts, 77, 17))
>b : Symbol(b, Decl(intraExpressionInferences.ts, 78, 6))
>R2 : Symbol(R2, Decl(intraExpressionInferences.ts, 75, 14))
};
function test<R1, R2>(foo: Chain<R1, R2>) {}
>test : Symbol(test, Decl(intraExpressionInferences.ts, 79, 2))
>R1 : Symbol(R1, Decl(intraExpressionInferences.ts, 81, 14))
>R2 : Symbol(R2, Decl(intraExpressionInferences.ts, 81, 17))
>foo : Symbol(foo, Decl(intraExpressionInferences.ts, 81, 22))
>Chain : Symbol(Chain, Decl(intraExpressionInferences.ts, 71, 3))
>R1 : Symbol(R1, Decl(intraExpressionInferences.ts, 81, 14))
>R2 : Symbol(R2, Decl(intraExpressionInferences.ts, 81, 17))
test({
>test : Symbol(test, Decl(intraExpressionInferences.ts, 79, 2))
a: () => 0,
>a : Symbol(a, Decl(intraExpressionInferences.ts, 83, 6))
b: (a) => 'a',
>b : Symbol(b, Decl(intraExpressionInferences.ts, 84, 15))
>a : Symbol(a, Decl(intraExpressionInferences.ts, 85, 8))
c: (b) => {
>c : Symbol(c, Decl(intraExpressionInferences.ts, 85, 18))
>b : Symbol(b, Decl(intraExpressionInferences.ts, 86, 8))
const x: string = b;
>x : Symbol(x, Decl(intraExpressionInferences.ts, 87, 13))
>b : Symbol(b, Decl(intraExpressionInferences.ts, 86, 8))
}
});
// Repro from #41712
class Wrapper<T = any> {
>Wrapper : Symbol(Wrapper, Decl(intraExpressionInferences.ts, 89, 3))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 93, 14))
public value?: T;
>value : Symbol(Wrapper.value, Decl(intraExpressionInferences.ts, 93, 24))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 93, 14))
}
type WrappedMap = Record<string, Wrapper>;
>WrappedMap : Symbol(WrappedMap, Decl(intraExpressionInferences.ts, 95, 1))
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
>Wrapper : Symbol(Wrapper, Decl(intraExpressionInferences.ts, 89, 3))
type Unwrap<D extends WrappedMap> = {
>Unwrap : Symbol(Unwrap, Decl(intraExpressionInferences.ts, 97, 42))
>D : Symbol(D, Decl(intraExpressionInferences.ts, 98, 12))
>WrappedMap : Symbol(WrappedMap, Decl(intraExpressionInferences.ts, 95, 1))
[K in keyof D]: D[K] extends Wrapper<infer T> ? T : never;
>K : Symbol(K, Decl(intraExpressionInferences.ts, 99, 5))
>D : Symbol(D, Decl(intraExpressionInferences.ts, 98, 12))
>D : Symbol(D, Decl(intraExpressionInferences.ts, 98, 12))
>K : Symbol(K, Decl(intraExpressionInferences.ts, 99, 5))
>Wrapper : Symbol(Wrapper, Decl(intraExpressionInferences.ts, 89, 3))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 99, 46))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 99, 46))
};
type MappingComponent<I extends WrappedMap, O extends WrappedMap> = {
>MappingComponent : Symbol(MappingComponent, Decl(intraExpressionInferences.ts, 100, 2))
>I : Symbol(I, Decl(intraExpressionInferences.ts, 102, 22))
>WrappedMap : Symbol(WrappedMap, Decl(intraExpressionInferences.ts, 95, 1))
>O : Symbol(O, Decl(intraExpressionInferences.ts, 102, 43))
>WrappedMap : Symbol(WrappedMap, Decl(intraExpressionInferences.ts, 95, 1))
setup(): { inputs: I; outputs: O };
>setup : Symbol(setup, Decl(intraExpressionInferences.ts, 102, 69))
>inputs : Symbol(inputs, Decl(intraExpressionInferences.ts, 103, 14))
>I : Symbol(I, Decl(intraExpressionInferences.ts, 102, 22))
>outputs : Symbol(outputs, Decl(intraExpressionInferences.ts, 103, 25))
>O : Symbol(O, Decl(intraExpressionInferences.ts, 102, 43))
map?: (inputs: Unwrap<I>) => Unwrap<O>;
>map : Symbol(map, Decl(intraExpressionInferences.ts, 103, 39))
>inputs : Symbol(inputs, Decl(intraExpressionInferences.ts, 104, 11))
>Unwrap : Symbol(Unwrap, Decl(intraExpressionInferences.ts, 97, 42))
>I : Symbol(I, Decl(intraExpressionInferences.ts, 102, 22))
>Unwrap : Symbol(Unwrap, Decl(intraExpressionInferences.ts, 97, 42))
>O : Symbol(O, Decl(intraExpressionInferences.ts, 102, 43))
};
declare function createMappingComponent<I extends WrappedMap, O extends WrappedMap>(def: MappingComponent<I, O>): void;
>createMappingComponent : Symbol(createMappingComponent, Decl(intraExpressionInferences.ts, 105, 2))
>I : Symbol(I, Decl(intraExpressionInferences.ts, 107, 40))
>WrappedMap : Symbol(WrappedMap, Decl(intraExpressionInferences.ts, 95, 1))
>O : Symbol(O, Decl(intraExpressionInferences.ts, 107, 61))
>WrappedMap : Symbol(WrappedMap, Decl(intraExpressionInferences.ts, 95, 1))
>def : Symbol(def, Decl(intraExpressionInferences.ts, 107, 84))
>MappingComponent : Symbol(MappingComponent, Decl(intraExpressionInferences.ts, 100, 2))
>I : Symbol(I, Decl(intraExpressionInferences.ts, 107, 40))
>O : Symbol(O, Decl(intraExpressionInferences.ts, 107, 61))
createMappingComponent({
>createMappingComponent : Symbol(createMappingComponent, Decl(intraExpressionInferences.ts, 105, 2))
setup() {
>setup : Symbol(setup, Decl(intraExpressionInferences.ts, 109, 24))
return {
inputs: {
>inputs : Symbol(inputs, Decl(intraExpressionInferences.ts, 111, 16))
num: new Wrapper<number>(),
>num : Symbol(num, Decl(intraExpressionInferences.ts, 112, 21))
>Wrapper : Symbol(Wrapper, Decl(intraExpressionInferences.ts, 89, 3))
str: new Wrapper<string>()
>str : Symbol(str, Decl(intraExpressionInferences.ts, 113, 43))
>Wrapper : Symbol(Wrapper, Decl(intraExpressionInferences.ts, 89, 3))
},
outputs: {
>outputs : Symbol(outputs, Decl(intraExpressionInferences.ts, 115, 14))
bool: new Wrapper<boolean>(),
>bool : Symbol(bool, Decl(intraExpressionInferences.ts, 116, 22))
>Wrapper : Symbol(Wrapper, Decl(intraExpressionInferences.ts, 89, 3))
str: new Wrapper<string>()
>str : Symbol(str, Decl(intraExpressionInferences.ts, 117, 45))
>Wrapper : Symbol(Wrapper, Decl(intraExpressionInferences.ts, 89, 3))
}
};
},
map(inputs) {
>map : Symbol(map, Decl(intraExpressionInferences.ts, 121, 6))
>inputs : Symbol(inputs, Decl(intraExpressionInferences.ts, 122, 8))
return {
bool: inputs.nonexistent,
>bool : Symbol(bool, Decl(intraExpressionInferences.ts, 123, 16))
>inputs : Symbol(inputs, Decl(intraExpressionInferences.ts, 122, 8))
str: inputs.num, // Causes error
>str : Symbol(str, Decl(intraExpressionInferences.ts, 124, 37))
>inputs.num : Symbol(num, Decl(intraExpressionInferences.ts, 112, 21))
>inputs : Symbol(inputs, Decl(intraExpressionInferences.ts, 122, 8))
>num : Symbol(num, Decl(intraExpressionInferences.ts, 112, 21))
}
}
});
// Repro from #48279
function simplified<T>(props: { generator: () => T, receiver: (t: T) => any }) {}
>simplified : Symbol(simplified, Decl(intraExpressionInferences.ts, 128, 3))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 132, 20))
>props : Symbol(props, Decl(intraExpressionInferences.ts, 132, 23))
>generator : Symbol(generator, Decl(intraExpressionInferences.ts, 132, 31))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 132, 20))
>receiver : Symbol(receiver, Decl(intraExpressionInferences.ts, 132, 51))
>t : Symbol(t, Decl(intraExpressionInferences.ts, 132, 63))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 132, 20))
function whatIWant<T>(props: { generator: (bob: any) => T, receiver: (t: T) => any }) {}
>whatIWant : Symbol(whatIWant, Decl(intraExpressionInferences.ts, 132, 81))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 134, 19))
>props : Symbol(props, Decl(intraExpressionInferences.ts, 134, 22))
>generator : Symbol(generator, Decl(intraExpressionInferences.ts, 134, 30))
>bob : Symbol(bob, Decl(intraExpressionInferences.ts, 134, 43))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 134, 19))
>receiver : Symbol(receiver, Decl(intraExpressionInferences.ts, 134, 58))
>t : Symbol(t, Decl(intraExpressionInferences.ts, 134, 70))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 134, 19))
function nonObject<T>(generator: (bob: any) => T, receiver: (t: T) => any) {}
>nonObject : Symbol(nonObject, Decl(intraExpressionInferences.ts, 134, 88))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 136, 19))
>generator : Symbol(generator, Decl(intraExpressionInferences.ts, 136, 22))
>bob : Symbol(bob, Decl(intraExpressionInferences.ts, 136, 34))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 136, 19))
>receiver : Symbol(receiver, Decl(intraExpressionInferences.ts, 136, 49))
>t : Symbol(t, Decl(intraExpressionInferences.ts, 136, 61))
>T : Symbol(T, Decl(intraExpressionInferences.ts, 136, 19))
simplified({ generator: () => 123, receiver: (t) => console.log(t + 2) })
>simplified : Symbol(simplified, Decl(intraExpressionInferences.ts, 128, 3))
>generator : Symbol(generator, Decl(intraExpressionInferences.ts, 138, 12))
>receiver : Symbol(receiver, Decl(intraExpressionInferences.ts, 138, 34))
>t : Symbol(t, Decl(intraExpressionInferences.ts, 138, 46))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>t : Symbol(t, Decl(intraExpressionInferences.ts, 138, 46))
whatIWant({ generator: (bob) => bob ? 1 : 2, receiver: (t) => console.log(t + 2) })
>whatIWant : Symbol(whatIWant, Decl(intraExpressionInferences.ts, 132, 81))
>generator : Symbol(generator, Decl(intraExpressionInferences.ts, 139, 11))
>bob : Symbol(bob, Decl(intraExpressionInferences.ts, 139, 24))
>bob : Symbol(bob, Decl(intraExpressionInferences.ts, 139, 24))
>receiver : Symbol(receiver, Decl(intraExpressionInferences.ts, 139, 44))
>t : Symbol(t, Decl(intraExpressionInferences.ts, 139, 56))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>t : Symbol(t, Decl(intraExpressionInferences.ts, 139, 56))
nonObject((bob) => bob ? 1 : 2, (t) => console.log(t + 2))
>nonObject : Symbol(nonObject, Decl(intraExpressionInferences.ts, 134, 88))
>bob : Symbol(bob, Decl(intraExpressionInferences.ts, 140, 11))
>bob : Symbol(bob, Decl(intraExpressionInferences.ts, 140, 11))
>t : Symbol(t, Decl(intraExpressionInferences.ts, 140, 33))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>t : Symbol(t, Decl(intraExpressionInferences.ts, 140, 33))
// Repro from #48466
interface Opts<TParams, TDone, TMapped> {
>Opts : Symbol(Opts, Decl(intraExpressionInferences.ts, 140, 58))
>TParams : Symbol(TParams, Decl(intraExpressionInferences.ts, 144, 15))
>TDone : Symbol(TDone, Decl(intraExpressionInferences.ts, 144, 23))
>TMapped : Symbol(TMapped, Decl(intraExpressionInferences.ts, 144, 30))
fetch: (params: TParams, foo: number) => TDone,
>fetch : Symbol(Opts.fetch, Decl(intraExpressionInferences.ts, 144, 41))
>params : Symbol(params, Decl(intraExpressionInferences.ts, 145, 12))
>TParams : Symbol(TParams, Decl(intraExpressionInferences.ts, 144, 15))
>foo : Symbol(foo, Decl(intraExpressionInferences.ts, 145, 28))
>TDone : Symbol(TDone, Decl(intraExpressionInferences.ts, 144, 23))
map: (data: TDone) => TMapped
>map : Symbol(Opts.map, Decl(intraExpressionInferences.ts, 145, 51))
>data : Symbol(data, Decl(intraExpressionInferences.ts, 146, 10))
>TDone : Symbol(TDone, Decl(intraExpressionInferences.ts, 144, 23))
>TMapped : Symbol(TMapped, Decl(intraExpressionInferences.ts, 144, 30))
}
function example<TParams, TDone, TMapped>(options: Opts<TParams, TDone, TMapped>) {
>example : Symbol(example, Decl(intraExpressionInferences.ts, 147, 1))
>TParams : Symbol(TParams, Decl(intraExpressionInferences.ts, 149, 17))
>TDone : Symbol(TDone, Decl(intraExpressionInferences.ts, 149, 25))
>TMapped : Symbol(TMapped, Decl(intraExpressionInferences.ts, 149, 32))
>options : Symbol(options, Decl(intraExpressionInferences.ts, 149, 42))
>Opts : Symbol(Opts, Decl(intraExpressionInferences.ts, 140, 58))
>TParams : Symbol(TParams, Decl(intraExpressionInferences.ts, 149, 17))
>TDone : Symbol(TDone, Decl(intraExpressionInferences.ts, 149, 25))
>TMapped : Symbol(TMapped, Decl(intraExpressionInferences.ts, 149, 32))
return (params: TParams) => {
>params : Symbol(params, Decl(intraExpressionInferences.ts, 150, 12))
>TParams : Symbol(TParams, Decl(intraExpressionInferences.ts, 149, 17))
const data = options.fetch(params, 123)
>data : Symbol(data, Decl(intraExpressionInferences.ts, 151, 13))
>options.fetch : Symbol(Opts.fetch, Decl(intraExpressionInferences.ts, 144, 41))
>options : Symbol(options, Decl(intraExpressionInferences.ts, 149, 42))
>fetch : Symbol(Opts.fetch, Decl(intraExpressionInferences.ts, 144, 41))
>params : Symbol(params, Decl(intraExpressionInferences.ts, 150, 12))
return options.map(data)
>options.map : Symbol(Opts.map, Decl(intraExpressionInferences.ts, 145, 51))
>options : Symbol(options, Decl(intraExpressionInferences.ts, 149, 42))
>map : Symbol(Opts.map, Decl(intraExpressionInferences.ts, 145, 51))
>data : Symbol(data, Decl(intraExpressionInferences.ts, 151, 13))
}
}
interface Params {
>Params : Symbol(Params, Decl(intraExpressionInferences.ts, 154, 1))
one: number
>one : Symbol(Params.one, Decl(intraExpressionInferences.ts, 156, 18))
two: string
>two : Symbol(Params.two, Decl(intraExpressionInferences.ts, 157, 15))
}
example({
>example : Symbol(example, Decl(intraExpressionInferences.ts, 147, 1))
fetch: (params: Params) => 123,
>fetch : Symbol(fetch, Decl(intraExpressionInferences.ts, 161, 9))
>params : Symbol(params, Decl(intraExpressionInferences.ts, 162, 12))
>Params : Symbol(Params, Decl(intraExpressionInferences.ts, 154, 1))
map: (number) => String(number)
>map : Symbol(map, Decl(intraExpressionInferences.ts, 162, 35))
>number : Symbol(number, Decl(intraExpressionInferences.ts, 163, 10))
>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>number : Symbol(number, Decl(intraExpressionInferences.ts, 163, 10))
});
example({
>example : Symbol(example, Decl(intraExpressionInferences.ts, 147, 1))
fetch: (params: Params, foo: number) => 123,
>fetch : Symbol(fetch, Decl(intraExpressionInferences.ts, 166, 9))
>params : Symbol(params, Decl(intraExpressionInferences.ts, 167, 12))
>Params : Symbol(Params, Decl(intraExpressionInferences.ts, 154, 1))
>foo : Symbol(foo, Decl(intraExpressionInferences.ts, 167, 27))
map: (number) => String(number)
>map : Symbol(map, Decl(intraExpressionInferences.ts, 167, 48))
>number : Symbol(number, Decl(intraExpressionInferences.ts, 168, 10))
>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>number : Symbol(number, Decl(intraExpressionInferences.ts, 168, 10))
});
example({
>example : Symbol(example, Decl(intraExpressionInferences.ts, 147, 1))
fetch: (params: Params, foo) => 123,
>fetch : Symbol(fetch, Decl(intraExpressionInferences.ts, 171, 9))
>params : Symbol(params, Decl(intraExpressionInferences.ts, 172, 12))
>Params : Symbol(Params, Decl(intraExpressionInferences.ts, 154, 1))
>foo : Symbol(foo, Decl(intraExpressionInferences.ts, 172, 27))
map: (number) => String(number)
>map : Symbol(map, Decl(intraExpressionInferences.ts, 172, 40))
>number : Symbol(number, Decl(intraExpressionInferences.ts, 173, 10))
>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>number : Symbol(number, Decl(intraExpressionInferences.ts, 173, 10))
});

View File

@@ -0,0 +1,590 @@
=== tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts ===
// Repros from #47599
declare function callIt<T>(obj: {
>callIt : <T>(obj: { produce: (n: number) => T; consume: (x: T) => void; }) => void
>obj : { produce: (n: number) => T; consume: (x: T) => void; }
produce: (n: number) => T,
>produce : (n: number) => T
>n : number
consume: (x: T) => void
>consume : (x: T) => void
>x : T
}): void;
callIt({
>callIt({ produce: () => 0, consume: n => n.toFixed()}) : void
>callIt : <T>(obj: { produce: (n: number) => T; consume: (x: T) => void; }) => void
>{ produce: () => 0, consume: n => n.toFixed()} : { produce: () => number; consume: (n: number) => string; }
produce: () => 0,
>produce : () => number
>() => 0 : () => number
>0 : 0
consume: n => n.toFixed()
>consume : (n: number) => string
>n => n.toFixed() : (n: number) => string
>n : number
>n.toFixed() : string
>n.toFixed : (fractionDigits?: number | undefined) => string
>n : number
>toFixed : (fractionDigits?: number | undefined) => string
});
callIt({
>callIt({ produce: _a => 0, consume: n => n.toFixed(),}) : void
>callIt : <T>(obj: { produce: (n: number) => T; consume: (x: T) => void; }) => void
>{ produce: _a => 0, consume: n => n.toFixed(),} : { produce: (_a: number) => number; consume: (n: number) => string; }
produce: _a => 0,
>produce : (_a: number) => number
>_a => 0 : (_a: number) => number
>_a : number
>0 : 0
consume: n => n.toFixed(),
>consume : (n: number) => string
>n => n.toFixed() : (n: number) => string
>n : number
>n.toFixed() : string
>n.toFixed : (fractionDigits?: number | undefined) => string
>n : number
>toFixed : (fractionDigits?: number | undefined) => string
});
callIt({
>callIt({ produce() { return 0; }, consume: n => n.toFixed()}) : void
>callIt : <T>(obj: { produce: (n: number) => T; consume: (x: T) => void; }) => void
>{ produce() { return 0; }, consume: n => n.toFixed()} : { produce(): number; consume: (n: number) => string; }
produce() {
>produce : () => number
return 0;
>0 : 0
},
consume: n => n.toFixed()
>consume : (n: number) => string
>n => n.toFixed() : (n: number) => string
>n : number
>n.toFixed() : string
>n.toFixed : (fractionDigits?: number | undefined) => string
>n : number
>toFixed : (fractionDigits?: number | undefined) => string
});
declare function callItT<T>(obj: [(n: number) => T, (x: T) => void]): void;
>callItT : <T>(obj: [(n: number) => T, (x: T) => void]) => void
>obj : [(n: number) => T, (x: T) => void]
>n : number
>x : T
callItT([() => 0, n => n.toFixed()]);
>callItT([() => 0, n => n.toFixed()]) : void
>callItT : <T>(obj: [(n: number) => T, (x: T) => void]) => void
>[() => 0, n => n.toFixed()] : [() => number, (n: number) => string]
>() => 0 : () => number
>0 : 0
>n => n.toFixed() : (n: number) => string
>n : number
>n.toFixed() : string
>n.toFixed : (fractionDigits?: number | undefined) => string
>n : number
>toFixed : (fractionDigits?: number | undefined) => string
callItT([_a => 0, n => n.toFixed()]);
>callItT([_a => 0, n => n.toFixed()]) : void
>callItT : <T>(obj: [(n: number) => T, (x: T) => void]) => void
>[_a => 0, n => n.toFixed()] : [(_a: number) => number, (n: number) => string]
>_a => 0 : (_a: number) => number
>_a : number
>0 : 0
>n => n.toFixed() : (n: number) => string
>n : number
>n.toFixed() : string
>n.toFixed : (fractionDigits?: number | undefined) => string
>n : number
>toFixed : (fractionDigits?: number | undefined) => string
// Repro from #25092
interface MyInterface<T> {
retrieveGeneric: (parameter: string) => T,
>retrieveGeneric : (parameter: string) => T
>parameter : string
operateWithGeneric: (generic: T) => string
>operateWithGeneric : (generic: T) => string
>generic : T
}
const inferTypeFn = <T>(generic: MyInterface<T>) => generic;
>inferTypeFn : <T>(generic: MyInterface<T>) => MyInterface<T>
><T>(generic: MyInterface<T>) => generic : <T>(generic: MyInterface<T>) => MyInterface<T>
>generic : MyInterface<T>
>generic : MyInterface<T>
const myGeneric = inferTypeFn({
>myGeneric : MyInterface<number>
>inferTypeFn({ retrieveGeneric: parameter => 5, operateWithGeneric: generic => generic.toFixed()}) : MyInterface<number>
>inferTypeFn : <T>(generic: MyInterface<T>) => MyInterface<T>
>{ retrieveGeneric: parameter => 5, operateWithGeneric: generic => generic.toFixed()} : { retrieveGeneric: (parameter: string) => number; operateWithGeneric: (generic: number) => string; }
retrieveGeneric: parameter => 5,
>retrieveGeneric : (parameter: string) => number
>parameter => 5 : (parameter: string) => number
>parameter : string
>5 : 5
operateWithGeneric: generic => generic.toFixed()
>operateWithGeneric : (generic: number) => string
>generic => generic.toFixed() : (generic: number) => string
>generic : number
>generic.toFixed() : string
>generic.toFixed : (fractionDigits?: number | undefined) => string
>generic : number
>toFixed : (fractionDigits?: number | undefined) => string
});
// Repro #38623
function make<M>(o: { mutations: M, action: (m: M) => void }) { }
>make : <M>(o: { mutations: M; action: (m: M) => void; }) => void
>o : { mutations: M; action: (m: M) => void; }
>mutations : M
>action : (m: M) => void
>m : M
make({
>make({ mutations: { foo() { } }, action: (a) => { a.foo() }}) : void
>make : <M>(o: { mutations: M; action: (m: M) => void; }) => void
>{ mutations: { foo() { } }, action: (a) => { a.foo() }} : { mutations: { foo(): void; }; action: (a: { foo(): void; }) => void; }
mutations: {
>mutations : { foo(): void; }
>{ foo() { } } : { foo(): void; }
foo() { }
>foo : () => void
},
action: (a) => { a.foo() }
>action : (a: { foo(): void; }) => void
>(a) => { a.foo() } : (a: { foo(): void; }) => void
>a : { foo(): void; }
>a.foo() : void
>a.foo : () => void
>a : { foo(): void; }
>foo : () => void
});
// Repro from #38845
declare function foo<A>(options: { a: A, b: (a: A) => void }): void;
>foo : <A>(options: { a: A; b: (a: A) => void; }) => void
>options : { a: A; b: (a: A) => void; }
>a : A
>b : (a: A) => void
>a : A
foo({
>foo({ a: () => { return 42 }, b(a) {},}) : void
>foo : <A>(options: { a: A; b: (a: A) => void; }) => void
>{ a: () => { return 42 }, b(a) {},} : { a: () => 42; b(a: () => 42): void; }
a: () => { return 42 },
>a : () => 42
>() => { return 42 } : () => 42
>42 : 42
b(a) {},
>b : (a: () => 42) => void
>a : () => 42
});
foo({
>foo({ a: function () { return 42 }, b(a) {},}) : void
>foo : <A>(options: { a: A; b: (a: A) => void; }) => void
>{ a: function () { return 42 }, b(a) {},} : { a: () => 42; b(a: () => 42): void; }
a: function () { return 42 },
>a : () => 42
>function () { return 42 } : () => 42
>42 : 42
b(a) {},
>b : (a: () => 42) => void
>a : () => 42
});
foo({
>foo({ a() { return 42 }, b(a) {},}) : void
>foo : <A>(options: { a: A; b: (a: A) => void; }) => void
>{ a() { return 42 }, b(a) {},} : { a(): 42; b(a: () => 42): void; }
a() { return 42 },
>a : () => 42
>42 : 42
b(a) {},
>b : (a: () => 42) => void
>a : () => 42
});
// Repro from #38872
type Chain<R1, R2> = {
>Chain : Chain<R1, R2>
a(): R1,
>a : () => R1
b(a: R1): R2;
>b : (a: R1) => R2
>a : R1
c(b: R2): void;
>c : (b: R2) => void
>b : R2
};
function test<R1, R2>(foo: Chain<R1, R2>) {}
>test : <R1, R2>(foo: Chain<R1, R2>) => void
>foo : Chain<R1, R2>
test({
>test({ a: () => 0, b: (a) => 'a', c: (b) => { const x: string = b; }}) : void
>test : <R1, R2>(foo: Chain<R1, R2>) => void
>{ a: () => 0, b: (a) => 'a', c: (b) => { const x: string = b; }} : { a: () => number; b: (a: number) => string; c: (b: string) => void; }
a: () => 0,
>a : () => number
>() => 0 : () => number
>0 : 0
b: (a) => 'a',
>b : (a: number) => string
>(a) => 'a' : (a: number) => string
>a : number
>'a' : "a"
c: (b) => {
>c : (b: string) => void
>(b) => { const x: string = b; } : (b: string) => void
>b : string
const x: string = b;
>x : string
>b : string
}
});
// Repro from #41712
class Wrapper<T = any> {
>Wrapper : Wrapper<T>
public value?: T;
>value : T | undefined
}
type WrappedMap = Record<string, Wrapper>;
>WrappedMap : WrappedMap
type Unwrap<D extends WrappedMap> = {
>Unwrap : Unwrap<D>
[K in keyof D]: D[K] extends Wrapper<infer T> ? T : never;
};
type MappingComponent<I extends WrappedMap, O extends WrappedMap> = {
>MappingComponent : MappingComponent<I, O>
setup(): { inputs: I; outputs: O };
>setup : () => { inputs: I; outputs: O;}
>inputs : I
>outputs : O
map?: (inputs: Unwrap<I>) => Unwrap<O>;
>map : ((inputs: Unwrap<I>) => Unwrap<O>) | undefined
>inputs : Unwrap<I>
};
declare function createMappingComponent<I extends WrappedMap, O extends WrappedMap>(def: MappingComponent<I, O>): void;
>createMappingComponent : <I extends WrappedMap, O extends WrappedMap>(def: MappingComponent<I, O>) => void
>def : MappingComponent<I, O>
createMappingComponent({
>createMappingComponent({ setup() { return { inputs: { num: new Wrapper<number>(), str: new Wrapper<string>() }, outputs: { bool: new Wrapper<boolean>(), str: new Wrapper<string>() } }; }, map(inputs) { return { bool: inputs.nonexistent, str: inputs.num, // Causes error } }}) : void
>createMappingComponent : <I extends WrappedMap, O extends WrappedMap>(def: MappingComponent<I, O>) => void
>{ setup() { return { inputs: { num: new Wrapper<number>(), str: new Wrapper<string>() }, outputs: { bool: new Wrapper<boolean>(), str: new Wrapper<string>() } }; }, map(inputs) { return { bool: inputs.nonexistent, str: inputs.num, // Causes error } }} : { setup(): { inputs: { num: Wrapper<number>; str: Wrapper<string>; }; outputs: { bool: Wrapper<boolean>; str: Wrapper<string>; }; }; map(inputs: Unwrap<{ num: Wrapper<number>; str: Wrapper<string>; }>): { bool: any; str: number; }; }
setup() {
>setup : () => { inputs: { num: Wrapper<number>; str: Wrapper<string>; }; outputs: { bool: Wrapper<boolean>; str: Wrapper<string>; }; }
return {
>{ inputs: { num: new Wrapper<number>(), str: new Wrapper<string>() }, outputs: { bool: new Wrapper<boolean>(), str: new Wrapper<string>() } } : { inputs: { num: Wrapper<number>; str: Wrapper<string>; }; outputs: { bool: Wrapper<boolean>; str: Wrapper<string>; }; }
inputs: {
>inputs : { num: Wrapper<number>; str: Wrapper<string>; }
>{ num: new Wrapper<number>(), str: new Wrapper<string>() } : { num: Wrapper<number>; str: Wrapper<string>; }
num: new Wrapper<number>(),
>num : Wrapper<number>
>new Wrapper<number>() : Wrapper<number>
>Wrapper : typeof Wrapper
str: new Wrapper<string>()
>str : Wrapper<string>
>new Wrapper<string>() : Wrapper<string>
>Wrapper : typeof Wrapper
},
outputs: {
>outputs : { bool: Wrapper<boolean>; str: Wrapper<string>; }
>{ bool: new Wrapper<boolean>(), str: new Wrapper<string>() } : { bool: Wrapper<boolean>; str: Wrapper<string>; }
bool: new Wrapper<boolean>(),
>bool : Wrapper<boolean>
>new Wrapper<boolean>() : Wrapper<boolean>
>Wrapper : typeof Wrapper
str: new Wrapper<string>()
>str : Wrapper<string>
>new Wrapper<string>() : Wrapper<string>
>Wrapper : typeof Wrapper
}
};
},
map(inputs) {
>map : (inputs: Unwrap<{ num: Wrapper<number>; str: Wrapper<string>; }>) => { bool: any; str: number; }
>inputs : Unwrap<{ num: Wrapper<number>; str: Wrapper<string>; }>
return {
>{ bool: inputs.nonexistent, str: inputs.num, // Causes error } : { bool: any; str: number; }
bool: inputs.nonexistent,
>bool : any
>inputs.nonexistent : any
>inputs : Unwrap<{ num: Wrapper<number>; str: Wrapper<string>; }>
>nonexistent : any
str: inputs.num, // Causes error
>str : number
>inputs.num : number
>inputs : Unwrap<{ num: Wrapper<number>; str: Wrapper<string>; }>
>num : number
}
}
});
// Repro from #48279
function simplified<T>(props: { generator: () => T, receiver: (t: T) => any }) {}
>simplified : <T>(props: { generator: () => T; receiver: (t: T) => any; }) => void
>props : { generator: () => T; receiver: (t: T) => any; }
>generator : () => T
>receiver : (t: T) => any
>t : T
function whatIWant<T>(props: { generator: (bob: any) => T, receiver: (t: T) => any }) {}
>whatIWant : <T>(props: { generator: (bob: any) => T; receiver: (t: T) => any; }) => void
>props : { generator: (bob: any) => T; receiver: (t: T) => any; }
>generator : (bob: any) => T
>bob : any
>receiver : (t: T) => any
>t : T
function nonObject<T>(generator: (bob: any) => T, receiver: (t: T) => any) {}
>nonObject : <T>(generator: (bob: any) => T, receiver: (t: T) => any) => void
>generator : (bob: any) => T
>bob : any
>receiver : (t: T) => any
>t : T
simplified({ generator: () => 123, receiver: (t) => console.log(t + 2) })
>simplified({ generator: () => 123, receiver: (t) => console.log(t + 2) }) : void
>simplified : <T>(props: { generator: () => T; receiver: (t: T) => any; }) => void
>{ generator: () => 123, receiver: (t) => console.log(t + 2) } : { generator: () => number; receiver: (t: number) => void; }
>generator : () => number
>() => 123 : () => number
>123 : 123
>receiver : (t: number) => void
>(t) => console.log(t + 2) : (t: number) => void
>t : number
>console.log(t + 2) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>t + 2 : number
>t : number
>2 : 2
whatIWant({ generator: (bob) => bob ? 1 : 2, receiver: (t) => console.log(t + 2) })
>whatIWant({ generator: (bob) => bob ? 1 : 2, receiver: (t) => console.log(t + 2) }) : void
>whatIWant : <T>(props: { generator: (bob: any) => T; receiver: (t: T) => any; }) => void
>{ generator: (bob) => bob ? 1 : 2, receiver: (t) => console.log(t + 2) } : { generator: (bob: any) => 2 | 1; receiver: (t: 2 | 1) => void; }
>generator : (bob: any) => 2 | 1
>(bob) => bob ? 1 : 2 : (bob: any) => 2 | 1
>bob : any
>bob ? 1 : 2 : 2 | 1
>bob : any
>1 : 1
>2 : 2
>receiver : (t: 2 | 1) => void
>(t) => console.log(t + 2) : (t: 2 | 1) => void
>t : 2 | 1
>console.log(t + 2) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>t + 2 : number
>t : 2 | 1
>2 : 2
nonObject((bob) => bob ? 1 : 2, (t) => console.log(t + 2))
>nonObject((bob) => bob ? 1 : 2, (t) => console.log(t + 2)) : void
>nonObject : <T>(generator: (bob: any) => T, receiver: (t: T) => any) => void
>(bob) => bob ? 1 : 2 : (bob: any) => 2 | 1
>bob : any
>bob ? 1 : 2 : 2 | 1
>bob : any
>1 : 1
>2 : 2
>(t) => console.log(t + 2) : (t: 2 | 1) => void
>t : 2 | 1
>console.log(t + 2) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>t + 2 : number
>t : 2 | 1
>2 : 2
// Repro from #48466
interface Opts<TParams, TDone, TMapped> {
fetch: (params: TParams, foo: number) => TDone,
>fetch : (params: TParams, foo: number) => TDone
>params : TParams
>foo : number
map: (data: TDone) => TMapped
>map : (data: TDone) => TMapped
>data : TDone
}
function example<TParams, TDone, TMapped>(options: Opts<TParams, TDone, TMapped>) {
>example : <TParams, TDone, TMapped>(options: Opts<TParams, TDone, TMapped>) => (params: TParams) => TMapped
>options : Opts<TParams, TDone, TMapped>
return (params: TParams) => {
>(params: TParams) => { const data = options.fetch(params, 123) return options.map(data) } : (params: TParams) => TMapped
>params : TParams
const data = options.fetch(params, 123)
>data : TDone
>options.fetch(params, 123) : TDone
>options.fetch : (params: TParams, foo: number) => TDone
>options : Opts<TParams, TDone, TMapped>
>fetch : (params: TParams, foo: number) => TDone
>params : TParams
>123 : 123
return options.map(data)
>options.map(data) : TMapped
>options.map : (data: TDone) => TMapped
>options : Opts<TParams, TDone, TMapped>
>map : (data: TDone) => TMapped
>data : TDone
}
}
interface Params {
one: number
>one : number
two: string
>two : string
}
example({
>example({ fetch: (params: Params) => 123, map: (number) => String(number)}) : (params: Params) => string
>example : <TParams, TDone, TMapped>(options: Opts<TParams, TDone, TMapped>) => (params: TParams) => TMapped
>{ fetch: (params: Params) => 123, map: (number) => String(number)} : { fetch: (params: Params) => number; map: (number: number) => string; }
fetch: (params: Params) => 123,
>fetch : (params: Params) => number
>(params: Params) => 123 : (params: Params) => number
>params : Params
>123 : 123
map: (number) => String(number)
>map : (number: number) => string
>(number) => String(number) : (number: number) => string
>number : number
>String(number) : string
>String : StringConstructor
>number : number
});
example({
>example({ fetch: (params: Params, foo: number) => 123, map: (number) => String(number)}) : (params: Params) => string
>example : <TParams, TDone, TMapped>(options: Opts<TParams, TDone, TMapped>) => (params: TParams) => TMapped
>{ fetch: (params: Params, foo: number) => 123, map: (number) => String(number)} : { fetch: (params: Params, foo: number) => number; map: (number: number) => string; }
fetch: (params: Params, foo: number) => 123,
>fetch : (params: Params, foo: number) => number
>(params: Params, foo: number) => 123 : (params: Params, foo: number) => number
>params : Params
>foo : number
>123 : 123
map: (number) => String(number)
>map : (number: number) => string
>(number) => String(number) : (number: number) => string
>number : number
>String(number) : string
>String : StringConstructor
>number : number
});
example({
>example({ fetch: (params: Params, foo) => 123, map: (number) => String(number)}) : (params: Params) => string
>example : <TParams, TDone, TMapped>(options: Opts<TParams, TDone, TMapped>) => (params: TParams) => TMapped
>{ fetch: (params: Params, foo) => 123, map: (number) => String(number)} : { fetch: (params: Params, foo: number) => number; map: (number: number) => string; }
fetch: (params: Params, foo) => 123,
>fetch : (params: Params, foo: number) => number
>(params: Params, foo) => 123 : (params: Params, foo: number) => number
>params : Params
>foo : number
>123 : 123
map: (number) => String(number)
>map : (number: number) => string
>(number) => String(number) : (number: number) => string
>number : number
>String(number) : string
>String : StringConstructor
>number : number
});

View File

@@ -0,0 +1,178 @@
// @strict: true
// @declaration: true
// Repros from #47599
declare function callIt<T>(obj: {
produce: (n: number) => T,
consume: (x: T) => void
}): void;
callIt({
produce: () => 0,
consume: n => n.toFixed()
});
callIt({
produce: _a => 0,
consume: n => n.toFixed(),
});
callIt({
produce() {
return 0;
},
consume: n => n.toFixed()
});
declare function callItT<T>(obj: [(n: number) => T, (x: T) => void]): void;
callItT([() => 0, n => n.toFixed()]);
callItT([_a => 0, n => n.toFixed()]);
// Repro from #25092
interface MyInterface<T> {
retrieveGeneric: (parameter: string) => T,
operateWithGeneric: (generic: T) => string
}
const inferTypeFn = <T>(generic: MyInterface<T>) => generic;
const myGeneric = inferTypeFn({
retrieveGeneric: parameter => 5,
operateWithGeneric: generic => generic.toFixed()
});
// Repro #38623
function make<M>(o: { mutations: M, action: (m: M) => void }) { }
make({
mutations: {
foo() { }
},
action: (a) => { a.foo() }
});
// Repro from #38845
declare function foo<A>(options: { a: A, b: (a: A) => void }): void;
foo({
a: () => { return 42 },
b(a) {},
});
foo({
a: function () { return 42 },
b(a) {},
});
foo({
a() { return 42 },
b(a) {},
});
// Repro from #38872
type Chain<R1, R2> = {
a(): R1,
b(a: R1): R2;
c(b: R2): void;
};
function test<R1, R2>(foo: Chain<R1, R2>) {}
test({
a: () => 0,
b: (a) => 'a',
c: (b) => {
const x: string = b;
}
});
// Repro from #41712
class Wrapper<T = any> {
public value?: T;
}
type WrappedMap = Record<string, Wrapper>;
type Unwrap<D extends WrappedMap> = {
[K in keyof D]: D[K] extends Wrapper<infer T> ? T : never;
};
type MappingComponent<I extends WrappedMap, O extends WrappedMap> = {
setup(): { inputs: I; outputs: O };
map?: (inputs: Unwrap<I>) => Unwrap<O>;
};
declare function createMappingComponent<I extends WrappedMap, O extends WrappedMap>(def: MappingComponent<I, O>): void;
createMappingComponent({
setup() {
return {
inputs: {
num: new Wrapper<number>(),
str: new Wrapper<string>()
},
outputs: {
bool: new Wrapper<boolean>(),
str: new Wrapper<string>()
}
};
},
map(inputs) {
return {
bool: inputs.nonexistent,
str: inputs.num, // Causes error
}
}
});
// Repro from #48279
function simplified<T>(props: { generator: () => T, receiver: (t: T) => any }) {}
function whatIWant<T>(props: { generator: (bob: any) => T, receiver: (t: T) => any }) {}
function nonObject<T>(generator: (bob: any) => T, receiver: (t: T) => any) {}
simplified({ generator: () => 123, receiver: (t) => console.log(t + 2) })
whatIWant({ generator: (bob) => bob ? 1 : 2, receiver: (t) => console.log(t + 2) })
nonObject((bob) => bob ? 1 : 2, (t) => console.log(t + 2))
// Repro from #48466
interface Opts<TParams, TDone, TMapped> {
fetch: (params: TParams, foo: number) => TDone,
map: (data: TDone) => TMapped
}
function example<TParams, TDone, TMapped>(options: Opts<TParams, TDone, TMapped>) {
return (params: TParams) => {
const data = options.fetch(params, 123)
return options.map(data)
}
}
interface Params {
one: number
two: string
}
example({
fetch: (params: Params) => 123,
map: (number) => String(number)
});
example({
fetch: (params: Params, foo: number) => 123,
map: (number) => String(number)
});
example({
fetch: (params: Params, foo) => 123,
map: (number) => String(number)
});