Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 996
Sophie Avatar asked Dec 24 '22 03:12

Sophie


2 Answers

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

like image 187
Titian Cernicova-Dragomir Avatar answered Jan 18 '23 23:01

Titian Cernicova-Dragomir


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

like image 37
Lexo Avatar answered Jan 19 '23 00:01

Lexo