Typescript Literal Types

Introduction

Literal types are a feature of the Typescript compiler that allows the creation of types that have a specific value of a primitive type.

Literal types can be of type string, number or boolean.

Let's take a look at literal types in code. Let's define a simple string variable, villian.

let villain = "Joker"

Notice we did not specify the type of the variable villain. However, the Typescript compiler will infer that villain is of type string i.e. let villian: string = "Joker".

Let's now declare a constant called hero.

const hero = "Batman"

Again we do not explicitly specify the type of hero and again we can assume that the Typescript compiler infers that hero is a string but in reality, the compiler does a wee bit more. It infers not only that hero is a string but that it is a string with an exact value, "Batman", a literal type i.e. const hero: "Batman".

Usage

By itself, literal types do not seem to provide a lot of value, however, they come in quite handy when used in conjunction with the union types. Let's take a look at a simple example.

Gotham City needs your help! The citizens have grown tired of Batman's binge drinking and late-night partying and have decided that Gotham doesn't need one hero, it needs two. The standards are high and the chosen hero has to be superb!

type Hero = "Batman" | "Superman"

const saveGotham = (h: Hero) => {
    // Imaginary hero stuff happens here...
    console.log(`Thank you ${h}!`)
}

saveGotham("Batman") // "Thank you Batman"
saveGotham("Superman") // "Thank you Superman"
saveGotham("Spiderman") // Argument of type '"Spiderman"' cannot be assigned to type 'hero'

Let's talk through this.

We define a union of string literals called Hero. A hero can either be a string with the value "Batman" or a string with the value "Superman".

We then define a function called saveGotham() that accepts a single argument of type Hero.

Executing the saveGotham() function with valid hero values results in the correct output i.e. "Batman" or "Superman".

Executing the saveGotham() function with an invalid hero value, "Spiderman", returns a compiler error, Argument of type '"Spiderman"' cannot be assigned to type 'hero'.

Brilliant!

"Spiderman" was never specified as a valid string literal for the Hero union type and we never wanted that web-flinging maniac saving Gotham anyway!

Conclusion

Literal types, on their own, aren't very useful however when combined with union types, provide a creative way to write powerful, type(value)-checked code to prevent unexpected results in our applications.

Happy coding!!!