born2net
born2net

Reputation: 24943

Can anyone explain this TypeScript snippet?

Interfaces are used as blueprints for a contract. And yet in TypeScript you have this odd syntax (essentially having a new() inside an interface). Is this some sort of factory?

interface IControllerDetails {
     controller : { new(...args:string[]): void ;};
}

tx for reading.

Upvotes: 0

Views: 442

Answers (3)

born2net
born2net

Reputation: 24943

basically, that syntax of someMember : { new(...args:string[]): IAnotherSample ;}; means the Class must have the same constructor signature that matches the interface contract. For anyone that needs the complete source here you go:

```

interface ISample {
    // someMember requires a class with a constructor that has matching signature and return type
    someMember : { new(...args:string[]): IAnotherSample ;};
}
interface IAnotherSample {
    someNum: number;
}
class MyClass implements IAnotherSample{
    public someNum:number;
    constructor(...args:string[]) {
    }
}

let sample: ISample = {
    someMember: MyClass
};

let sampleInstance = new sample.someMember('123');

```

Upvotes: 0

David Sherret
David Sherret

Reputation: 106620

It means that the controller property of objects that conform to the interface have a constructor and the constructor can take any number of string parameters.

So you can write code like the following:

let controllerDetails: IControllerDetails = ...;

let controller = new controllerDetails.controller("any", "amount", "of string args");

The weird part is that when creating new instances of the controller property it returns void. So in the code shown, controller is of type void. I'm not sure why someone would want to do that unless just calling new controllerDetails.controller() did all that was necessary, but even still that's strange.

An example of a value that conforms to the interface would be something like this:

class Controller {
    constructor(...args: string[]) {
    }
}

let controllerDetails: IControllerDetails = {
    // you could inline a class here if you wanted by using a class expression
    controller: Controller
};

Edit: By "inline", I just meant you could write this if you wanted, which isn't commonly done:

let controllerDetails: IControllerDetails = {
    controller: class Controller {
        constructor(...args: string[]) {
        }
    }
};

Upvotes: 3

Ryan Cavanaugh
Ryan Cavanaugh

Reputation: 220944

To break this down:

interface IControllerDetails {
     controller : { new(...args:string[]): void ;};
}

Let's start here

interface IControllerDetails {

This declares a type called IControllerDetails

     controller : { new(...args:string[]): void ;};
     ~~~~~~~~~~

It has a property called controller

     controller : { new(...args:string[]): void ;};
                  ~                              ~

The type of the controller property is an object type with some members. There could have been more properties declared between the {}s, but there's only one here

     controller : { new(...args:string[]): void ;};
                    ~~~

The only member of the controller property is a construct signature. This means you can invoke the new operator on the controller property.

     controller : { new(...args:string[]): void ;};
                        ~~~           ~~

This constructor takes between zero and infinity arguments.

     controller : { new(...args:string[]): void ;};
                           ~~~~

The name of the parameter list is args, though this doesn't affect anything.

     controller : { new(...args:string[]): void ;};
                                ~~~~~~

All of the arguments have to be of type string

     controller : { new(...args:string[]): void ;};
                                           ~~~~

The constructor doesn't have to return anything. In practice, what they're saying here is that you can return an object of any kind (because it's safe to assign a function returning more to a function returning less).

Upvotes: 3

Related Questions