justTryIt
justTryIt

Reputation: 67

How to use the original map key when using the Mapped Types with the Template Literal Types?

I need a types like this:

type A<Map extends object, Keys extends Extract<keyof Map, string>> = {
    [NewKey in `prefix-${Keys}`]: Map[Keys/*!!!problem here!!!*/]
}

I don't know how to deal with the code where the comment is located. Keys does not split union types with NewKey, it is always be keyof Map!


This is types A actual work:

type B = A<{ a: 1, b: 2 }, "a" | "b">
/*
type B => {
  "prefix-a": 1 | 2,
  "prefix-b": 1 | 2
}
*/

But I want a "type C":

// type C = ...
type D = C<{ a: 1, b: 2 }, "a" | "b">
/*
type D => {
  "prefix-a": 1,
  "prefix-b": 2
}
*/

Upvotes: 1

Views: 85

Answers (2)

Kelvin Schoofs
Kelvin Schoofs

Reputation: 8718

You can use key remapping like this:

type C<Map extends object, Keys extends Extract<keyof Map, string>> = {
    [Key in Keys as `prefix-${Key}`]: Map[Key]
}

type D = C<{ a: 1, b: 2 }, "a" | "b">
//type D = {
//    "prefix-a": 1;
//    "prefix-b": 2;
//}

Upvotes: 2

justTryIt
justTryIt

Reputation: 67

Well, I came up with the answer myself...

type GetKey<FromKey extends string> = FromKey extends `prefix-${infer Key}` ? Key : never

type A<Map extends object, Keys extends Extract<keyof Map, string>> = {
    [NewKey in `prefix-${Keys}`]: Map[GetKey<NewKey>]
}

type B = A<{ a: 1, b: 2 }, "a" | "b">
/* B => {
  "prefix-a": 1,
  "prefix-b": 2
}
*/

Upvotes: 2

Related Questions