TypeScript: Incorrect inference of arrow function with intersected mapped type argument under strictFunctionTypes
TypeScript 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
About this issue
- Original URL
- State: open
- Created 5 years ago
- Comments: 17 (5 by maintainers)
I would, too, but as it turns out a
Readonly<any>isn’t structurally compatible with aReadonly<{x: number}>because of howanyfeeds into mapped types…Unreliableis supposed to be “fallback to structural if varianced-based check fails” whileUnmeasurableis “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 allUnreliableintoUnmeasurableis performance, in practice I’m not sure that’s the case.