How Intrinsic Type Manipulations work in TypeScript
Tags: typescript, javascript, webdev, tutorial
Published: 2022-06-19 17:04:31

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:
```typescript
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`:
```typescript
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.
```typescript
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:
```typescript
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](https://fjolt.com/article/typescript-template-literal-types), 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:
```typescript
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. 
```typescript
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.