Uncommon TypeScript Features

For the last couple of months I’ve been working with TypeScript a lot. Many cool features came to my mind and now I see more ways to use them. Here I would like to share some interesting features of TypeScript that I find interesting but not really common. None of these features are super unique(some of them could be even found in docs)

Enumeration

TypeScript allows you to create a union of types like so type Coffee = Latte | Espresso | Americano . And this even works with strings or numbers like type Coffee = “latte” | “americano” and type CoffeeId = 1 | 2 | 3

However this gets worse if you need to specify a big range of numbers. In this case if you don’t want to check your range conditionaly, you may find it usefull to create an IntRange type:

type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N
  ? Acc[number]
  : Enumerate<N, [...Acc, Acc['length']]>

type IntRange<F extends number, T extends number> 
    = Exclude<Enumerate<T>, Enumerate<F>>

const num: IntRange<20, 300> = 200 // It's Ok
const num: IntRange<20, 300> = 1000 // This will give you an error

Required and Partial

Those three types are actually from . But among many others I find them particularly usefull.

The Required is a type wrapper that makes all fields… well… required. This way you can make something like:

type Coffee = { // Say, you found this type in readonly library
  coffeeBeans: Beans,
  steamedMilk?: true,
  hotChocolate?: true,
};

//////////////////////////////

type Mocha = Required<Coffee>;
//const mocha: Mocha = {  // Error, hotChocolate is not specified
//  coffeeBeans: Beans.Columbia,
//  steamedMilk: true,
//};

const mocha: Mocha = { // It's Ok  
  coffeeBeans: Beans.Columbia,
  steamedMilk: true,
  hotChocolate: true,
};

Partial does exactly the oposite making all your fields optional. That’s especially usefull when you are going to update some entity and you don’t want to provide all the types of existing one:

type Entity = {
  name: string,
  description: string
}

///////////////

function updateEntity(id: string, newEntity: Partial<Entity>) {
  db.findEntity(id).update(newEntity);
}

///////////////

updateEntity(id, {description: {'New Description'})

Type of array elements

One time you may want to retrieve type of an array element. You can do this with the next type:

type ArrayElement<ArrayType extends readonly unknown[]> = 
  ArrayType extends readonly (infer ElementType)[] ? ElementType : never;

Check out thread for more

Last Updated: October 30th, 2022

TypeScript