How Intrinsic Type Manipulations work in TypeScript


Did you know that TypeScript comes with a bunch of built in string manipulator types? That means we can easily transform a string type into uppercase, lowercase, or capitalized versions of itself. When might this be useful? In lots of situations where you have a fixed set of string values, for example whenever you have a set of strings from an object using something like [keyof](https://fjolt.com/article/typescript-keyof).

To transform a string into a different version by defining a new type along with one of the type manipulators. For example, below we transform myType into the capitalized version:

type myType = "hi there" type capitalizedMyType = Capitalize<myType> let myVar:capitalizedMyType = "Hi there";

In the above example, hi there would throw an error - only Hi there will work with a Capitalize type. Similarly, we can uncapitalize a string using Uncapitalize:

type myType = "HI THERE" type uncapitalizedMyType = Uncapitalize<myType> let myVar:uncapitalizedMyType = "hI THERE";

Above, only hI THERE will work. Any other case will fail the check.

Uppercase and Lowercase Intrinsic Type Manipulation

Along with Capitalize, we also have Uppercase and Lowercase. They both do exactly what you think they’d do - one changes all characters to uppercase, and the other to lowercase.

type myType = "this long sentence" type bigMyType = Uppercase<myType> let myVar:bigMyType = "THIS LONG SENTENCE"

Lowercase intrinsic type manipulation

Above we’ve created a type which is the uppercase version of myType. Here is the same example, but in the other direction: making the lowercase version:

type myType = "THIS LONG SENTENCE" type smallMyType = Lowercase<myType> let myVar:smallMyType = "this long sentence"

Using with template literals

These types become very useful when working with template literals, where we can enforce a string literal to use a lowercase version - for example for an ID. Here is a version where we have a set number of strings, and we only want to use the lowercase version in the ID, as part of the versionId type:

type versions = "DEV" | "PROD" | "STAGING" type versionPrefix = "gold-" | "beta-" | "alpha-" type versionId = `${versionPrefix}${Lowercase<versions>}` let currentVersion:versionId = "gold-dev"

Above, we have two sets of union types, and we combine them into one versionId. Here, we only accept lowercase letters, but version is uppercase. We can transform it with Lowercase, so gold-dev is valid.

Using with keyof objects

In a similar way, we may receive an object from an API or elsewhere, which has odd or uneven casing. To normalise this, we can use intrinsic type manipulations. Below, I am using keyof to get all the keys in myObject, and making them all lowercase too.

type myObject = { firstName: string, Age: number, Lastname: string } type keys = Lowercase<keyof myObject> let getObjectKey:keys = "firstname"

keys only has the following valid values: firstname | age | lastname. In this example, using intrinsic string manipulation like this can be an easy way to create clean types when the data we have at our disposal has issues.

Last Updated Saturday, 18 June 2022
Johnny Simpson
Johnny Simpson

More from Typescript

Subscribe for Daily Dev Tips

Subscribe to our weekly newsletter, to stay up to date with our latest web development and software engineering posts via email. You can opt out at any time.

Not a valid email