[SOLVED] String replace when creating string literal union type in typescript


I have a string literal union type that looks like this:

type LowerCaseNames = 'youku-frame' | 'youku' | 'mini-program' | 'tiktok-frame';

This is only an example, since my union type is a list of more than 100 cases.

What I need to have is a new type where I would have the following "values" in type:

type UpperCaseNames = 'YOUKU_FRAME' | 'YOUKU' | 'MINI_PROGRAM' | 'TIKTOK_FRAME';

So far, I am using TypeScript’s Uppercase type in order to have it upper-cased.

type UpperCaseNames = `${Uppercase<LowerCaseNames>}`;

What this returns is upper-cased union type but, I still have in them - instead of _.
Is there a way for me to create a type that I can use like this ${Replace<Uppercase<LowerCaseNames>>} in order to replace - with _?
I am using Typescript v4.4.4.


You can write a custom Replace<T, S, D> utility type which takes a string literal type T and produces a new version where occurrences of a source string S are replaced with a destination string D. Here’s one way to do it:

type Replace<T extends string, S extends string, D extends string,
  A extends string = ""> = T extends `${infer L}${S}${infer R}` ?
  Replace<R, S, D, `${A}${L}${D}`> : `${A}${T}`

That’s a tail-recursive template literal type which uses a type parameter A to accumulate the result. If T is of the form L+S+R for some (possibly empty) "left part" L and some (possibly empty) "right part" R, then you want to use L as-is, replace S with D, and then continue doing Replacements on R. Otherwise, T doesn’t contain S and you just want to use T as-is.

Let’s try it out:

type LowerCaseNames = 'youku-frame' | 'youku' | 'mini-program' | 'tiktok-frame';

type UpperCaseNames = Uppercase<Replace<LowerCaseNames, "-", "_">>
// type UpperCaseNames = "YOUKU" | "YOUKU_FRAME" | "MINI_PROGRAM" | "TIKTOK_FRAME"

Looks good!

Playground link to code

Answered By – jcalz

Answer Checked By – David Goodson (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *