Generic Constraints in TypeScript

Using Generic Parameters we can create a method, class, or interface that accepts many types. But this may not be what we need. Sometimes we need to limit the types of values. This is where we use the generic constraints in TypeScript.

Generic Constraints

Generic constraints allow us to narrow down the type of a Generic Parameter. i.e. we limit the values that a generic parameter can accept.

Consider the following code. PrintMe is a generic method. It will accept any value. As you can see it will even take null & undefined.

We want the function to accept only a string or a number. We do that by using the extends keyword.

T extends number|string in the following example, limits the T to either a number or string. Hence passing an object, boolean, null, or undefined results in a compiler error.

You can also extend from an empty object. Since String, Number, Boolean, etc are also subclasses of Object type, they are allowed. But null and undefined are not, hence they result in a compiler error.

You can even extend from an Object (O in upper case), with a similar effect.

If you wish to only accept objects i.e. non primitive types, then you can extend from an object (o in lower case). Note that the object is a Typescript-only type. You can’t assign to it any primitive type like bool, number, string, symbol, etc.

Generic Constraints Examples

Constraining an object

Consider the following example, where we print the length of an object. The compiler throws the error because it cannot determine whether the arg has a length property.

We can extend the T from an object with a length property {length:number}.

We can also extend from an interface. In the example, we create an interface ILength with property length and use that to constrain T

Type Parameter that is constrained by another Type Parameter

We can declare a type parameter that is constrained by another type parameter.

The getPropertyValue() function accepts an object (target) and a property name (key). It returns the value of the property. But this code results in an error Type 'K' cannot be used to index type 'T'.

Here we use bracket notation (target[key]) to access the value of a property. Typescript cannot guarantee that we accidentally use a property that does not exist.

Hence we use the Keyof type operator to create a new Type Parameter to extend the type T

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top