Sophie
Sophie

Reputation: 501

How to write a TypeScript function accepting a class implementing an interface as a parameter?

I want to write a function which accepts a class as an argument, but only classes which implement a specific interface.

I know that I can use any, but it would be nice to rely on the type system to enforce this.

Some pseudocode to express what I mean...

interface MyInterface { ... }
class Class1 implements MyInterface { ... }
class Class2 { ... }

function doStuff(classParameter: Class implements MyInterface) { ... }
doStuff(Class1); // OK
doStuff(Class2); // Error

Upvotes: 5

Views: 4559

Answers (2)

Lexo
Lexo

Reputation: 95

Maybe you can use generics to achieve what you want to do. Here's a workaround :

function doStuff<T extends myInterface>(classParameter: T) {
  ...
}

So here, T is a dynamic type which necessary implements myInterface (yeah, keyword extends while talking about interfaces is strange here).

You can check the documentation below, part "Generic constraints" https://www.typescriptlang.org/docs/handbook/generics.html

Upvotes: 3

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 250256

You can use a constructor signature to enforce the fact that the constructor will return an instance compatible with the interface. You can use it either as a generic parameter constraint or directly as a parameter depending on what you need to do with the class:

interface MyInterface { foo: number }
class Class1 implements MyInterface { foo: number }
class Class2 { bar: number }

function doStuff0(classParameter: new (...args: any[]) => MyInterface) { }
doStuff0(Class1); // OK
doStuff0(Class2); // Error

function doStuff1<T  extends new (...args: any[]) => MyInterface>(classParameter: T) {  }
doStuff1(Class1); // OK
doStuff1(Class2); // Error

Note I added members to the example, don't forget Typescript uses a structural type system, so compatibility is determined by members not by implements MyInterface declaration, so any class would be compatible if MyInterface were empty, and a class would be compatible if it had a foo member even if it didn't explicitly declare implements MyInterface

Upvotes: 12

Related Questions