If I have a TypeScript type like
type O = { strKey: string; numKey: number; boolKey: boolean };
is it possible to define a type definition NameValue
such that NameValue<O>
would create the new type
type OAttrs =
| { name: "strKey"; value: string }
| { name: "numKey"; value: number }
| { name: "boolKey"; value: boolean };
This could be useful when using Object.fromEntries
to create an object of type O
from a list of attributes, for example.
Two attempts that don't work.
This first attempt is not legal TypeScript.
// export type NameValue1<T> = { name: P extends keyof T, value: T[P] };
// Cannot find name 'P'. ts(2304)
The second attempt does not succeed in making the value
type specific to the corresponding name
.
export type NameValue2P<T, P extends keyof T> = { name: P; value: T[P] };
export type NameValue2<T> = NameValue2P<T, keyof T>;
export type ONameValue2 = NameValue2<O>;
// type ONameValue2 = {
// name: keyof O;
// value: string | number | boolean;
// }
You can use a mapped type which maps over the properties of O
. Afterwards, you can index the mapped type with keyof O
producing the desired union.
type NameValue<O> = {
[K in keyof O]: {
name: K,
value: O[K]
}
}[keyof O]
type O = { strKey: string; numKey: number; boolKey: boolean };
type OAttrs = NameValue<O>
// type OAttrs = {
// name: "strKey";
// value: string;
// } | {
// name: "numKey";
// value: number;
// } | {
// name: "boolKey";
// value: boolean;
// }