Incorrect inference of arrow function with intersected mapped type argument under strictFunctionTypes
See original GitHub issueTypeScript Version: 3.6.0-dev.20190801
Search Terms: inference
intersection type
strictFunctionTypes
Code
type MappedIntersection<T extends {}> = { [P in keyof T]: string } & {};
type MappedRaw<T extends {}> = { [P in keyof T]: string };
// Case 1: Intersection + no arrow = succeed
type ToInferNoArrowIntersection<T extends {}> = {
fn(params: MappedIntersection<T>): void;
};
type NoArrowIntersection<T extends ToInferNoArrowIntersection<any>> = void;
declare const case1: NoArrowIntersection<{
fn: (params: MappedIntersection<{a: 1}>) => string,
}>;
// Case 2: No intersection + arrow = succeed
type ToInferArrowNoIntersection<T extends {}> = {
fn: (params: MappedRaw<T>) => void;
};
type ArrowNoIntersection<T extends ToInferArrowNoIntersection<any>> = void;
declare const case2: ArrowNoIntersection<{
fn: (params: MappedRaw<{a: 1}>) => void,
}>;
// Case 3: Intersection + arrow = fail
type ToInferArrowIntersection<T extends {}> = {
fn: (params: MappedIntersection<T>) => void;
};
type ArrowIntersection<T extends ToInferArrowIntersection<any>> = void;
declare const case3: ArrowIntersection<{ // Fails here
fn: (params: MappedIntersection<{a: 1}>) => void,
}>;
Expected behavior: Expected case 3 to succeed.
Actual behavior: Case 3 produces:
Type '{ fn: (params: { a: string; }) => void; }' does not satisfy the constraint 'ToInferArrowIntersection<any>'.
Types of property 'fn' are incompatible.
Type '(params: { a: string; }) => void' is not assignable to type '(params: { [x: string]: string; }) => void'.
Types of parameters 'params' and 'params' are incompatible.
Property 'a' is missing in type '{ [x: string]: string; }' but required in type '{ a: string; }'.
Seems relevant that compilation succeeds without strictFunctionTypes
Playground Link: Playground
Related Issues: https://github.com/microsoft/TypeScript/issues/29123#issuecomment-453884098 https://github.com/microsoft/TypeScript/issues/31081
Issue Analytics
- State:
- Created 4 years ago
- Comments:17 (5 by maintainers)
Top Results From Across the Web
Typescript arrow functions vs normal functions in interfaces ...
P.S. I browsed through a few SO questions, including this one about arrow function vs. normal function inside interface but none of them...
Read more >7 The essentials of TypeScript - Exploring JS
Type inference is not guesswork: It follows clear rules (similar to arithmetic) for deriving types where they haven't been specified explicitly. In this...
Read more >TSConfig Reference - Docs on every TSConfig option
A TSConfig file in a directory indicates that the directory is the root of a ... strictNullChecks ": false ... Strict Function Types...
Read more >Grumbling on TypeScript - stafford williams
Grumbling on TypeScript · Missing Type Definitions won't slow me down# · TSX breaks Generic Arrow functions# · Whacky type inference on Generics...
Read more >Overview - TypeScript
During type argument inference in TypeScript 3.4, for a call to a generic function that returns a function type, TypeScript will, as appropriate, ......
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I would, too, but as it turns out a
Readonly<any>
isn’t structurally compatible with aReadonly<{x: number}>
because of howany
feeds into mapped types…Unreliable
is supposed to be “fallback to structural if varianced-based check fails” whileUnmeasurable
is “don’t use the variance result at all”. It was a bit of a compromise to continue to allow some things that checked with variance but not by structure, so the change would break less, iirc. In theory the only thing that would change by converting allUnreliable
intoUnmeasurable
is performance, in practice I’m not sure that’s the case.