artemnih
artemnih

Reputation: 4209

How to ensure that argument type of Class implements an interface

I have a class that implements interface IField

export class FieldImplementation implements IField { };

And a service that stores types:

import { FieldImplementation } from '../component';
...
service.addField(FieldImplementation);

I need to ensure that the argument passed to addField implements IField.

Currently addField looks like this:

addField(field: any) {
...
}

Upvotes: 1

Views: 616

Answers (1)

jcalz
jcalz

Reputation: 329838

You're looking for the constructor signature, also known as a "newable" type. You want the parameter to addField() to be something you call new on to get an IFIeld. That is representable like this:

addField(field: new(...args: any[])=>IField) {
  // ...
  new field(/* some kind of arguments */);
}

That signature will accept any constructor producing an IField, but there could be a mismatch with the arguments that constructor accepts.


If you are expecting field to be called with new and a particular number and type of arguments, you can express that too. For example, if you want field to be a no-arg constructor:

addField(field: new()=>IField) {
  // ...
  new field(); // no arguments
}

Then, if FieldImplementation is a class with a no-arg constructor, it will succeed:

service.addField(FieldImplementation); // okay

whereas a class that requires a constructor parameter will fail, which is good:

class NeedAString implements IField { 
  constructor(private myString: string) { }
};
service.addField(NeedAString); // error, NeedAString is not a no-arg constructor
// error is desirable because you don't want addField() implementation
// to call new NeedAString();

Hope that helps. Good luck!

Upvotes: 1

Related Questions