7

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.

2
  • 1
    One would think it would automatically convert - to _ buuut apparently that's a limitation of the Uppercase<T> type Commented Mar 4, 2022 at 14:25
  • 4
    I mean, "-".toUpperCase() is just "-" so I'm not sure why you think it would be "_". (Capitalization is not the same as pushing a shift key on a keyboard) Commented Mar 4, 2022 at 14:35

2 Answers 2

22

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

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

4 Comments

I have 2 questions. Is there a way to use regex as the input, or is that too complicated? Is there a way to cycle through multiple input characters and replace them with its corresponding output? I tried doing type ReplaceAll<T> = Replace<Replace<T, ']', '}'>, '[', '{'> but I'm getting a T does not satisfy 'string' error.
That's weird. Even though I'm getting that error, it still works. I have this input type const of /test/[id] and I'm getting the correct type of /test/{id}
Oh lol nvm. I think I fixed it myself. I just needed to add a <T extends string>. I'm still free for suggestions though on the multiple input chars
I don't understand what you mean by multiple input characters, exactly. You're looking for some kind of thing like ReplaceAll<"abcdefghi", {cde: "CDE", gh: "GH"}> to produce "abCDEfGHi" maybe? The details of potential overlap would be tricky and this comment section of a two-year-old answer isn't a great place to discuss this. If you want to open a new question post for it you might get more useful engagement.
2

here is an example of how we can do this for a single type

type B = 'youku-frame';
type Replace<S extends string> = S extends `${infer A}-${infer B}`
  ? `${Uppercase<A>}_${Uppercase<B>}`
  : ${Uppercase<B>};

type C = Replace<B>;

References

  1. https://github.com/microsoft/TypeScript/pull/40336
  2. https://github.com/microsoft/TypeScript/pull/40580#issuecomment-731124971
  3. https://devblogs.microsoft.com/typescript/announcing-typescript-4-1-beta/#template-literal-types

2 Comments

It should be noted that this may produce unexpected behavior for input strings that contain fewer than or more than a single - character. If you pass in "yooku" or "tic-tac-toe" then you will get unknown and TIC_TAC-TOE, respectively.
Thank you @jcalz, updated to work for "yooku" and "tic-tac-toe" needs to be in your way, your answer looks like the best solution

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.