Skip to main content

extends in generic parameters

1. General form

javascript
function example<T extends Constraint>(value: T) { ... }
  • T is the type parameter (generic).
  • extends Constraint is the constraint that T must satisfy.

TypeScript checks whether T can be considered a subtype of Constraint. If not, the compiler throws an error.


Example 1: a shape constraint

javascript
function printLength<T extends { length: number }>(value: T) { console.log(value.length); } printLength("hello"); // a string has length printLength([1, 2, 3]); // an array has length printLength(123); // a number does not have length

Here T must be a type that has a length: number property.


Example 2: a base-type constraint

javascript
function toStringValue<T extends string | number>(value: T): string { return value.toString(); } toStringValue("abc"); // string toStringValue(123); // number toStringValue(true); // boolean is not part of the allowed union

Here T is constrained by the union: string | number.


Example 3: an interface constraint

javascript
interface Identifiable { id: string; } function logId<T extends Identifiable>(obj: T) { console.log(obj.id); } logId({ id: "123", name: "Tim" }); // OK logId({ name: "Alex" }); // missing id

T is required to contain an id field.


Example 4: dependent generic parameters

javascript
function getProp<T, K extends keyof T>(obj: T, key: K) { return obj[key]; } const user = { id: 1, name: "Tim" }; getProp(user, "id"); // OK getProp(user, "age"); // "age" is not a key of user

Here K depends on T and is constrained to only the object's allowed keys.


Example 5: a constraint for classes and constructors

javascript
type Constructor<T> = new (...args: any[]) => T; function createInstance<T extends Constructor<any>>(Ctor: T) { return new Ctor(); }

T must be a constructor (a class) so that it can be instantiated via new.


Example 6: a constraint for dictionaries (Record)

javascript
function sumValues<T extends Record<string, number>>(obj: T): number { return Object.values(obj).reduce((a, b) => a + b, 0); } sumValues({ a: 1, b: 2 }); // OK sumValues({ x: 1, y: "two" }); // a string, not number

Record<string, number> means: an object whose keys are strings and values are numbers.


Example 7: extends + a default value

javascript
function identity<T extends string | number = string>(value: T): T { return value; } identity("hi"); // OK identity(42); // OK identity(true); // boolean does not satisfy the constraint

What extends actually does in generic parameters

  1. Constrains the substitutable type - T must extend (be a subtype of) the given type.
  2. Guarantees properties - you can access them without errors.
  3. Improves type inference - TS knows more about the possible structure of T.
  4. Does not create inheritance! - it is not the extends from classes, but a logical type constraint.

Example without extends -> an error

javascript
function getLength<T>(value: T): number { return value.length; // TS Error: T might not have length }

Fixed:

javascript
function getLength<T extends { length: number }>(value: T) { return value.length; // OK }

Summary

Purpose of extendsExampleWhat it provides
Shape constraint<T extends { id: string }>Guarantees the presence of fields
Union constraint<T extends string | number>Only the listed types
Interface constraint<T extends Identifiable>Only types that implement the interface
Parameter dependency<K extends keyof T>The key must belong to the object
Class constraint<T extends new (...args) => any>Only constructors
Dictionary constraint<T extends Record<string, number>>Objects with a defined value type

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.