Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make a generic TypeScript interface extend from another generic interface?

Tags:

typescript

I have an interface, with several elements:

export interface Item {
  id: string;
  code: string;
  createdAt: string;
  updatedAt: string;
  level: number;
  seq: number;
  hasChildren: boolean;

  parentObject?: Item;
  children?: Item[];
}

I wanted something like the Partial<T> which I helpfully discovered here: Make all properties within a Typescript interface optional

However, I would like to make one of the fields mandatory. I implemented this:

export interface ItemUpdate extends Partial<Item> {
  id: string;
}

and that compiled well. However, I would like to avoid declaring it for each interface. For that, I made it more generic:

export interface UpdateOf<T> extends Partial<T> {
  id: string; // the ID is the only mandatory value for an update
}

However, that is no longer compiling, returning the following error:

error TS2312: An interface may only extend a class or another interface.

I am running Angular 6.1.5, which comes with Typescript 2.9 (as far as I know).

like image 345
Daniel Gray Avatar asked Nov 01 '18 22:11

Daniel Gray


People also ask

Can an interface extend another interface TypeScript?

An interface can be extended by other interfaces. In other words, an interface can inherit from other interface. Typescript allows an interface to inherit from multiple interfaces. Use the extends keyword to implement inheritance among interfaces.

Can generic types extend generic types?

We can add generic type parameters to class methods, static methods, and interfaces. Generic classes can be extended to create subclasses of them, which are also generic.

How do I extend an existing interface?

You can also use the extends keyword to extend an interface with existing type aliases.


1 Answers

The error message is out of date; there is an open issue to update it. The current rule is that a class or interface can only extend an object type or intersection of object types with statically known members, since the compiler needs to check whether the types of properties declared in the class or interface are compatible with the types of the corresponding properties (if any) of the base type. The members of Partial<Item> are statically known, while the members of Partial<T> are not. A workaround is to use an intersection type instead of a sub-interface:

export type UpdateOf<T> = Partial<T> & {id: string};
like image 179
Matt McCutchen Avatar answered Dec 08 '22 08:12

Matt McCutchen