TypeScript Utility Types

TypeScript includes a number of useful utility types. Below are a few I developed myself that I find useful.

NewRecord and NewOrExisting

I write a lot of code that reads/writes records from APIs. Most of the time these records have a numeric id field. Most of the time, this id field must be populated. However, in certain circumstances, such as creation of a new record, this id field might be undefined.

Initially, my records would be defined as

interface SomeRecordType { id?: number; field1: string; field2: string; /* etc */ }

However, this meant constantly having to perform checks that id was not undefined. When in most cases, id would not be undefined. So I created NewRecord and NewOrExisting, which looks as follows:

type NewRecord<T extends { id: number }> = { id?: undefined } & Omit<T, 'id'> type NewOrExisting<T extends { id: number }> = T | NewRecord<T>

This now allows me to define my interface as

interface SomeRecordType { id: number; field1: string; field2: string; /* etc */ }

And then in those situations where I might be working with a new record, I can explicitly type the record as such. This explicit typing also helps make clear which methods accept new/potentially new records and which don't.

Formify

I originally called this type FormData, but soon discovered that the name FormData is already in use, so I opted for Formify instead. This will modify a type such that any property is now allowed to be either its original type or an empty string. This is useful for setting initial values for form data using libraries such as Formik.

type Formify<T> = { [P in keyof T]: T[P] | ''; };