Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How can I map the values within a readonly array to another array using a mapping object within the typescript type system?

I’m having a bit of issue creating a type that maps the values within a readonly array to different values.

I’m making some progress and I’ve now got the following type.

const test = ['Hello', 'Hello_There'] as const;

export type RenameBy<Input extends readonly string[], Map extends Partial<Record<Input[number], unknown>>> = keyof {
  [K in Input[number] as K extends keyof Map ? (Map[K] extends string ? Map[K] : never) : K]: never;
};

// "hello" | "helloThere"
type Renamed = RenameBy<typeof test, { Hello: 'hello'; Hello_There: 'helloThere' }>;

As you can see, I’m making it into an object then retrieving the keys as that’s all I need. I’m wondering if there’s a nicer way to do this?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

And if not, how can I then convert a union type back into a readonly array? Any help would be much appreciated!

** Edit **

Okay I was making it much harder for myself. I now have the following type which is nicer. it still outputs a union not a new readonly array which is what I want

export type RenameBy<
  Input extends readonly string[],
  Map extends Partial<Record<Input[number], unknown>>,
> = Map[Input[number]] extends string ? Map[Input[number]] : Input[number];

>Solution :

It seems like you’re looking for a way to map the values within a readonly array to another array using a mapping object within the TypeScript type system. Here’s one approach you could take:

const test = ['Hello', 'Hello_There'] as const;

type Map<T extends readonly string[]> = { [K in T[number]]: string };

type RenameBy<T extends readonly string[], M extends Map<T>> = {
  [K in keyof M]: K extends T[number] ? M[K] : never;
};

type Renamed = RenameBy<typeof test, { Hello: 'hello'; Hello_There: 'helloThere' }>;

type RenamedArray = ReadonlyArray<Renamed[keyof Renamed]>;
const renamedArray: RenamedArray = ['hello', 'helloThere'];

First, we define a Map type that takes in a readonly string array T and maps each string in the array to a string value.

Next, we define the RenameBy type, which takes in a readonly string array T and a mapping object M that maps values in T to new values. We create a new object type that maps each key in M to the new value in M if the key is present in T, and never otherwise.

Finally, we use the keyof operator to get a union type of all the keys in the resulting object, and we use that union type to define a new readonly array type RenamedArray that contains the new values from the mapping object.

You can see in the example above that RenamedArray is inferred to be ReadonlyArray<"hello" | "helloThere">, which is the desired output.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading