Home > Enterprise >  Creating a Lookup Object with Template Literal Types
Creating a Lookup Object with Template Literal Types

Time:01-26

I've got a type defined as:

type Response = 'n_a' | 'n_o' | 'yes' | 'no'

I'd like to have a type that enforces that underscores are replaced with slashes:

type ReplaceUnderscoreWithSlash<T extends string> = 
     T extends `${infer Head}_${infer Tail}` ? `${Head}/${Tail}` : T;

Everything works as expected here:

type HumanReadableResponses = ReplaceUnderscoreWithSlash<Response>;

Now, I'd like to create a lookup object that I can use at runtime to convert from the underscore versions to the "human readable" versions but I'd like for the association to be typesafe.

I tried writing this as

type LookupObject<T extends string> = Record<T, ReplaceUnderscoreWithSlash<T>>;

However, this doesn't provide key -> value type safety like I was hoping to achieve since this appears to be valid:

const lookupObject: LookupObject<Response> = {
  n_a: 'n/a',
  n_o: 'n/a', // <---- I'd like it if this threw an error because the only valid value should be 'n/o'
  no: 'no',
  yes: 'yes',
};

Is what I'm trying to accomplish here possible?

CodePudding user response:

You need to corelate each key with the / version of the key. You can do this with a custom mapped type:

type LookupObject<T extends string> = {
  [P in T] : ReplaceUnderscoreWithSlash<P>
}

const lookupObject: LookupObject<Response> = {
  n_a: 'n/a',
  n_o: 'n/a', // error
  no: 'no',
  yes: 'yes',
};

Playground Link

  •  Tags:  
  • Related