Home > Software design >  TypeScript: Is it possible to derive a type that lists the attribute names and types of another obje
TypeScript: Is it possible to derive a type that lists the attribute names and types of another obje

Time:10-19

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;
// }

CodePudding user response:

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 OAttrs = NameValue<O>

// type OAttrs = {
//     name: "strKey";
//     value: string;
// } | {
//     name: "numKey";
//     value: number;
// } | {
//     name: "boolKey";
//     value: boolean;
// }

Playground

  • Related