0

Typescript 4.1 introduced template-literal-types which now allow us to map strings. Take the following interfaces as example:

interface User {
    id: number;
    userName: string;
    age: number;
}

interface Post {
    id: number;
    author: User;
    subject: string;
    body: string;
}

interface Queue {
   id: number;
   size: number;
   posts: Post[];
}

what I now want to do is mapping the Queue to a type with the property-path as key and the value as type like so:

// I want to do this:
type Properties = MapProperties<Queue>;

// ... to get the same result as this:
type Properties = {
    'id': number;                    // Queue > id
    'size': number;                  // Queue > size
    'posts.id': number;              // Queue > Post > id
    'posts.author.id': number;       // Queue > Post > User > id
    'posts.author.userName': string; // Queue > Post > User > userName
    'posts.author.age': number;      // Queue > Post > User > age
    'posts.subject': string;         // Queue > Post > subject
    'posts.body': string;            // Queue > Post > body
};

What I've managed so far is extracting the whole set of keys. Just mapping them to the type seems impossible to me:

// Removing the `keyof` won't work...
type MapProperties<T> = keyof {
    [
        K in keyof T as T[K] extends object ? `${K & string}.${MapProperties<T[K]> & string}` :
            T extends Array<infer U> ? MapProperties<U> : K
    ]?: T[K]
}

Is there a way to achieve what I'm trying to do? I also want to make it recursive so that it's not limited to a certain depth (excluding circular references).

Simon
  • 2,686
  • 2
  • 31
  • 43
  • I don’t get the logic behind `posts.id`; isn’t `posts` an array? It doesn’t have an `id` property; it has numeric indices. – jcalz Jan 29 '21 at 13:50
  • @jcalz I'm resolving the arrays item-type with `T extends Array ...`. `U` will be the type of what we have an array from :) – Simon Jan 29 '21 at 13:55
  • Translating the code from the other question here yields [this](https://tsplay.dev/Qmb8Bw). – jcalz Jan 29 '21 at 14:10

0 Answers0