0

I'm trying to generate template literals based on the keys from a generic type. I am using this to extract only the keys of properties that are objects, which works but only with any strings as such:

type KeysWithValsOfType<T, V> = keyof { [P in keyof T as T[P] extends V ? P : never]: P };

type Person = {
  firstName: string;
  lastName: string;
};

type Customer = {
  title: string;
  email: string;
};

type Booking = {
  id: string;
  person: Person;
  customer: Customer;
};

type TemplateLiteral<T> = `${string & KeysWithValsOfType<T>}($select=${string})`;

type BookingTemplate = TemplateLiteral<Booking>;

/**
 * BookingTemplate type can be either of these:
 * 
 * person($select=${string})
 * customer($select=${string})
 */

Is it possible to achieve the commented template literals where typescript generates based on the keys of the nested objects?

type TemplateLiteral<T> = `${string & KeysWithValsOfType<T>}($select=${???})`;

type BookingTemplate = TemplateLiteral<Booking>;

/**
 * BookingTemplate can be either of these:
 * 
 * person($select=firstName)
 * person($select=lastName)
 * person($select=firstName,lastName)
 * customer($select=title)
 * customer($select=email)
 * customer($select=title,email)
 */
Philip
  • 137
  • 1
  • 2
  • 16
  • Does [this approach](https://tsplay.dev/mL52VW) meet your needs? Note that if the property types have a lot of keys, this will generate enormous unions and explode the compiler. With `firstName` and `lastName` it's fine, but if you have more than seven or eight keys this isn't going to work. Anyway, if this works for you I could write up an answer explaining; otherwise, what am I missing? – jcalz Dec 06 '22 at 20:31
  • Thanks for your comment @jcalz. Yeah, you are completely right in that it will explode the compiler. I think I will have to resolve it differently writing a parser in JavaScript which traverses through a different structure, generating the expected string. – Philip Dec 06 '22 at 22:25
  • I'm confused... you'd still need to write a JS parser because template literal types, like the rest of the type system, are erased when TS compiles to JS. The template literal types would only help developers writing TS code. Is that not what you're looking for? Depending on your actual use case it might be possible to write something that works better, but I don't think I understand your actual use case. Could you clarify? – jcalz Dec 06 '22 at 23:53
  • Yeah I figured instead of writing the type literals I went with creating [this solution](https://tsplay.dev/Wok8gW). Then I wrote a parser in JavaScript that unwraps the nested object and creates the string that I was aiming for with the template literal types. Should've done it to begin with for this use case. Thanks for your help! Made me realise I was off in my approach. – Philip Dec 10 '22 at 00:53

0 Answers0