0

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) {
...
}
artemnih
  • 4,136
  • 2
  • 18
  • 28
  • 1
    you want the argument to be a class constructor that makes `IField` objects? That would be `addField(field: new(...args: any[])=>IField)`. Do you have a restriction on the number of arguments to that constructor? – jcalz Nov 05 '18 at 17:10
  • "I can still pass other classes that do not implement IField". Show us, please. I think either `IField` is empty (and this is a question about [structural typing](https://github.com/Microsoft/TypeScript/wiki/FAQ#what-is-structural-typing) in disguise) or something else is going on. Either way we need to see more code I think. – jcalz Nov 05 '18 at 17:18
  • "Only one argument can be passed" an argument of what type? In case it's not clear, I'm asking about the argument(s) to the `constructor()` inside any `class` that `implements IField`. – jcalz Nov 05 '18 at 17:20
  • @jcalz actually I'm sorry. It does work. If you create an answer, I will accept it. Thanks – artemnih Nov 05 '18 at 17:27

1 Answers1

1

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!

jcalz
  • 264,269
  • 27
  • 359
  • 360