I was reading this article about what's new in typescript 4.6 and I came across this weird syntax.
Could someone please explain what it does?
type UnionRecord<P extends keyof TypeMap> = { [K in P]:
{
kind: K;
v: TypeMap[K];
f: (p: TypeMap[K]) => void;
}
}[P];
The {}[P] : this [P] followed by the {}. Why is it there?
The full typescript code is given below.
interface TypeMap {
"number": number;
"string": string;
"boolean": boolean;
}
type UnionRecord<P extends keyof TypeMap> = { [K in P]:
{
kind: K;
v: TypeMap[K];
f: (p: TypeMap[K]) => void;
}
}[P];
function processRecord<K extends keyof TypeMap>(record: UnionRecord<K>) {
return record.f(record.v);
}
processRecord({
kind: "string",
v: "hello!",
// 'val' used to implicitly have the type 'string | number | boolean',
// but now is correctly inferred to just 'string'.
f: val => {
console.log(val.toUpperCase());
}
})
CodePudding user response:
Without the [P]
you'd get a map with keys from P
, in this example this would be a map with a subset of the keys "number", "string" and "boolean".
By adding an index lookup with the entire set of keys P
this instead evaluates to a union type of all possible values for the given keys or explicit: Inter["number"] | Inter["string"] | Inter["boolean"]
where
type Inter<P extends keyof TypeMap> = {
[K in P]: {
kind: K;
v: TypeMap[K];
f: (p: TypeMap[K]) => void;
}
}
For another example consider:
interface User {
firstName: string;
lastName: string;
active: boolean;
}
type UserFieldTypes = User[keyof User]
// UserFieldTypes is User['fistName'] | User['lastName'] | User['active']
// which equals string | string | boolean
Feel free to ask when there's still something unclear to you.