Stop misusing TypeScript type assertions

Tim Deschryver
Tim Deschryver
timdeschryver.dev
Reading mode

I'm writing this so you don't make the same mistake as our team. Without knowing how much impact type assertions would have, our team started to use them everywhere.

This started out great. We had type-safety in our code, and we felt safe to future changes. At least, we thought so.

In retrospect, we now know that we had created a false sense of security. We had created a safety net with a lot of holes, which defeats the purpose of having a safety net.

To give a simple example, let's first take a quick look at the Customer interface.

inferface Customer {
customerId: string;
name: string;
}

Now, let's see how we used type assertions to create a new customer instance.

// inline creation with type assertion
const customer = { customerId: newid(), name: 'Sarah' } as Customer;
// or a variant with angle brackets
const customer = <Customer>{ customerId: newid(), name: 'Sarah' };
// with a factory method
function createCustomer(name: string) {
return { customerId: newid(), name } as Customer;
}

This code has two problems concerning the correctness of these objects when the respective type is changed:

The simple fix is to ditch the type assertions and to replace them with type annotations and return types.

// inline creation with using a type annotation
const customer: Customer = { customerId: newid(), name: 'Sarah' };
// with a return type on the factory method
function createCustomer(name: string): Customer {
return { customerId: newid(), name };
}

With the updated snippet, we now get correct and helpful compile errors when the type is modified.

// no compile errors
const customerBad = { customerId: newid() } as Customer;
// with compile errors
const customerGood: Customer = { customerId: newid() };
~~~~~~~~~~~~ Property 'name' is missing in type '{ customerId: string; }' but required in type 'Customer'

To enforce this practice, you can enable the ESLint rule Enforces consistent usage of type assertions (consistent-type-assertions).

Fiddle with this example in the following TypeScript playground.

Feel free to update this blog post on GitHub, thanks in advance!

Enjoying the blog?

Support my work

If you enjoyed this post and found it useful, consider supporting my work. It helps me keep creating and sharing content like this. Thank you!