Skip to content

What makes a good generic and what makes a bad one?

Daisho Komiyama edited this page Feb 23, 2024 · 2 revisions

A good generic lets type information flow through it, and you won't lose type information.

In TypeScript, understanding how to write good generics is essential. But what distinguishes a good generic from a bad one? Let's delve into the nuances.

interface HasId {
     id: string
}

function example1<T extends HasId[]>(list:T) {
     return list.pop()
}

function example2<T extends HasId>(list:T[]) {
     return list.pop()
}

class Payment implements HasId {
     id = '0123'
}

class Invoice implements HasId {
     id = 'INVOICE_099'
}

const result1 = example1([new Payment(), new Invoice(), new Payment()])
//    ^ const result1: HasId | undefined

const result2 = example2([new Payment(), new Invoice(), new Payment()])
//    ^ const result2: Payment | Invoice | undefined

In this scenario, example2 emerges as a superior choice in terms of generic implementation, while example1 falls short. But why?

Understanding the distinction

The crucial difference lies in the preservation of type information.

Consider the return types of result1 and result2: HasId | undefined and Payment | Invoice | undefined, respectively.

  • result1 yields the type HasId, which merely guarantees the existence of an id property. This type lacks the specificity required to treat objects as instances of a particular class.

  • Conversely, result2 offers a union type of Payment and Invoice, providing more precise information about the returned objects.

Simplicity in constraints

The key takeaway here is to specify constraints in the simplest manner possible.

In example2, we explicitly define two constraints for the argument type: T and []. T extends HasId, ensuring the presence of an id property, while [] indicates an array structure, allowing for a clearer representation of the input.

On the other hand, example1 lacks this clarity, leading to a loss of type information.

Remember, "A good generic lets type information flow through it".

Clone this wiki locally