-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Description
TypeScript Version: 3.7.0-dev.20190910
Also tested in 3.6.2, 3.5.2
Search Terms:
conditional mapped inference inferred
Code
// Simple mapped type and inferrence
type Mapped<T> = { [K in keyof T]: { name: T[K] } };
type InferFromMapped<T> = T extends Mapped<infer R> ? R : never;
// Object literal type and associated mapped type
// Note that in the real code we don't have a direct reference to LiteralType
type LiteralType = {
first: "first";
second: "second";
}
type MappedLiteralType = {
first: { name: "first" },
second: { name: "second" },
};
type Inferred = InferFromMapped<MappedLiteralType>;
// UNEXPECTED resolves to false
type Test1 = Inferred extends Record<any, string> ? true : false;
// true as expected
type Test2 = LiteralType extends Record<any, string> ? true : false;
// true as expected; currently using this as a workaround
type Test3 = Inferred extends Record<keyof Inferred, string> ? true : false;
Expected behavior:
As Inferred
and LiteralType
are equivalent, we would expect Inferred extends Record<any, string>
to resolve to true just as the case with LiteralType
does.
Actual behavior:
Test1
resolves to false. This has the same behavior for similar expressions of the record (e.g. Record<string, string>
, { [key: string]: string }
); interestingly though, if we write the record Record<keyof Inferred, string>
we get the expected behavior, this is the current workaround I'm using.
We also get the expected behavior if we instead defined MappedLiteralType as Mapped<LiteralType>
. However in the code I encountered this, we have no direct access to LiteralType, only Inferred; I added LiteralType to the example only for demonstration of the expected behavior.
Playground Link:
Related Issues: