mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-10 18:04:18 -05:00
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:
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
192
tests/baselines/reference/intraExpressionInferences.errors.txt
Normal file
192
tests/baselines/reference/intraExpressionInferences.errors.txt
Normal 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)
|
||||
});
|
||||
|
||||
342
tests/baselines/reference/intraExpressionInferences.js
Normal file
342
tests/baselines/reference/intraExpressionInferences.js
Normal 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;
|
||||
}
|
||||
560
tests/baselines/reference/intraExpressionInferences.symbols
Normal file
560
tests/baselines/reference/intraExpressionInferences.symbols
Normal 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))
|
||||
|
||||
});
|
||||
|
||||
590
tests/baselines/reference/intraExpressionInferences.types
Normal file
590
tests/baselines/reference/intraExpressionInferences.types
Normal 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
|
||||
|
||||
});
|
||||
|
||||
@@ -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)
|
||||
});
|
||||
Reference in New Issue
Block a user