TypeScript string literal types are a great tool that let you define a type as a literal string value. They’re also really useful when combined with type unions, commonly used as a sort of alternative to enums, when you just want to deal with strings.
Here’s a simple example of a string literal union. Anything defined as the Colour type has to be one of those three strings.
type Colour = 'red' | 'green' | 'blue';
If you’re experienced in TypeScript/JavaScript, you might be familiar with String Interpolation, which lets you create a string by adding placeholders for variables.
const name = 'Ruby';
const age = 27;
const favouriteColour = 'green';
const message = `Hi, I'm ${name}, I'm ${age} years old, and my favourite colour is ${favouriteColour}`;
The string gets evaluated by replacing our placeholder values with the statements inside of them.
TypeScript lets you do something very similar with string literal types, creating template literal types. In their simplest form, you can do something like this:
type Foo = 'foo';
type Bar = 'bar';
type FooBar = `${Foo}${Bar}`; //foobar
We can do even more powerful things with this, however, thanks to TypeScript providing some great functionality to help us out.
Unions
If you use string interpolation with a type union made of string literal types, TypeScript will automatically create a type union with all the possible combinations.
Let’s take our previous colour example. What if we wanted to create a type to store variants for colours, e.g. light red, dark blue?
type ColourShade = 'light' | 'dark';
type Colour = 'red' | 'green' | 'blue';
type ColourVariant = ??
We could create this manually, but we can accomplish this faster using some TypeScript cleverness.
type ColourVariant = `${ColourShade}_${Colour}`; //"light_red" | "light_green" | "light_blue" | "dark_red" | "dark_green" | "dark_blue"
TypeScript automatically iterates through the type union, generating all the combinations for you. and this works for any number of options:
type MyFavouriteLetters = 'a' | 'b' | 'c'...;
type MyFavouriteWords = `${MyFavouriteLetters}${MyFavouriteLetters}${MyFavouriteLetters}${MyFavouriteLetters}${MyFavouriteLetters}`;
//aaaaa | aaaab | aaaac | aaaad ... | ccccc
You can use this to build as complex types as you like, from combining colours to a type that covers every possible 5 letter word, like above.
Utility Types
TypeScript contains a lot of helpful generic utility types, which can help for things like extracting the result type from a Promise using Awaited<T>, or converting all the properties of an object to optional or required, using Partial<T> or Required<T>. It also contains some utility types for string transformation.
Using our previous example again, we have a nice colour palette containing colours and their shades, from “lightred” to “darkblue”. You might notice in this example everything is lowercase, which might be what you want, but what if we wanted our strings to be formatted differently, using snake_case, camelCase, or something similar?
There are currently four utility types in TypeScript to help with this, and they’re all very self explanatory.
type ColourShade = 'light' | 'dark';
type Colour = 'red' | 'green' | 'blue';
type ColourVariant = `${Capitalize<ColourShade>}_${Capitalize<Colour>}`; // "Light_Red" | "Light_Green" | "Light_Blue" | "Dark_Red" | "Dark_Green" | "Dark_Blue"
Here I’ve used Capitalize<T> to, of course, capitalize my lowercase types and make the first letter a capital.
The three other types are:
- Uppercase<T> – This will convert the whole word to uppercase.
- Lowercase<T> – This will convert the whole word to lowercase.
- Uncapitalize<T> – The opposite of Capitalize<T>; it will make the first letter lowercase.
And of course you are welcome to create your own!
Conclusion
Thanks for reading my introduction to string interpolation, or template literals in TypeScript. If you’re interested, check out our article on conditional types, which can be used with template literals for some powerful results.
💬 Leave a comment