3

I have a type that looks like this:

type Config = {
  endpoints: [
    {name: "abc", created: false},
    {name: "xyz", created: true},
  ]
}

I have a function that transforms this type into the following:

type Instance = {
  abc: {name: "abc", created: false},
  xyz: {name: "xyz", created: false},
}

I wrote the following transformation type

type IntersectOf<U extends any> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;

type Transform<T extends Config, K extends (keyof T)[] = (keyof T)[]> = IntersectOf<{
  [key in keyof K]:
    K[key] extends keyof T['endpoints']
    // here it says "name" can't be used as index of `T["endpoints"][K[key]]`
    ? Record<T['endpoints'][K[key]]['name'], T['endpoints'][K[key]]>
    : never;
}[number]>;

type Instance = Transform<Config>;

I also tried adding a number type guard, and the error goes away but Instance becomes unknown. Here is the Transform type with number typeguard:

type Trasnform<T extends Config, K extends (keyof T)[] = (keyof T)[]> = IntersectOf<{
  [key in keyof K]:
    K[key] extends keyof T['endpoints']
    ? K[key] extends number
    ? Record<T['endpoints'][K[key]]['name'], T['endpoints'][K[key]]>
    : never
    : never;
}[number]>;

2 Answers 2

3

My suggestion would be to write a key-remapping mapped type that acts on the union of element types of the endpoints property, like this:

type Transform<T extends { name: string }> =
    { [U in T as U['name']]: U }

And then you pass in, not Config, but the indexed access type Config['endpoints'][number] corresponding to the element types:

type Instance = Transform<Config['endpoints'][number]>;

That produces this:

/* type Instance = {
    abc: {
        name: "abc";
        created: false;
    };
    xyz: {
        name: "xyz";
        created: true;
    };
} */

which is what you were looking for.

Playground link to code

Sign up to request clarification or add additional context in comments.

2 Comments

Working on the union, nice!
thanks a lot, I came across Key Remapping too but I wasn't able to make it work for my use case, Its working fine now
1

A proposal (playground):

export type IndicesOf<T> = Exclude<keyof T, keyof any[]>;

type Instance = { 
  [Idx in IndicesOf<Config["endpoints"]> 
    as Config["endpoints"][Idx]["name"]]: Config["endpoints"][Idx]
}

1 Comment

thanks a lot, I really liked the IndicesOf approach.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.