Web Development
4m ago
1.6k

This TypeScript Trick Will Blow Your Mind

Extracting Custom Types from String Arrays

This TypeScript Trick Will Blow Your Mind
This image has been generated by AI
“In the world of TypeScript, custom types emerge from string arrays like hidden gems.”

Join our Vibrant Discord Community for exclusive information and insightful discussions

TypeScript is an amazing tool to manipulate existing data and develop great practices.

Today we will explore how to extract a full name from a string array in the correct manner to ensure a clean type-safe output.

So without further ado… Let's get right into it.


The Problem

Let's begin by examining this code and understanding the problem with it:

  • This code uses an array of names to be searched.
  • The function findName takes a string surname and returns the associated full name.

The problem arises when you input "Doee" into the function findName.

This inconspicuous spelling error gives us an undefined output, which may cause bugs later down the line since nothing is stops us from making this error.

This is where TypeScript jumps in.

If we ensure findName only accepts literal Surnames, i.e. Craciun, Doe, Pigeon, then the compiler should shout at us when we enter inputs such as "Doee" which do not exist in the names array.

The Solution

We have established the only valid arguments for findName needs to consist of all existing surnames.

To achieve this, we create a generic type called ExtractSurname.

The code for ExtractSurname may seem difficult, but we will dissect it step-by-step:

1. Here ExtractSurname takes a generic argument T, which refers to any literal string using the extends operator.

In ExtractSurname<”Daniel”>, The value of T would equal "Daniel".

2. Next we apply the Typescript ternary operator, which is similar to the JavaScript ternary, but we are comparing types instead of real data.

3. We know the format of our names array is “<Name> <Surname>”, so here the infer keyword extracts subtypes from T.

In ExtractSurname<”Daniel Craciun”>:

  • infer Firstname = “Daniel”
  • infer Surname = “Craciun”

4. Lastly, if the input satisfies our format of “<Name> <Surname>”, return the Surname as a type, else return null.


Ok, so we have our ExtractSurname type ready.

Now we need a Surname type to represent all the surnames inside names.

1. names satisfies the format from ExtractSurname of “<Name> <Surname>

2. We use as const to narrow down the type of names to an array of literal strings.

This means we cast the type of names from string to:

readonly [“Daniel Craciun”, “John Doe”, “Harry Pigeon”].

3. The argument (typeof names)[number] represents the type of each indexed element inside names:

“Daniel Craciun” | “John Doe” | “Harry Pigeon”

4. Finally, this is the resulting type of Surname:

Blog Image

The last step is to update our findName function defined earlier with a new function findNameUsingSurname as follows:

And here is the Typescript compiler performing its magic as we expected:

Blog Image

If you enjoyed this article, please make sure to Subscribe, Clap, Comment and Connect with me today! 🌐

References