How do I determine the signature of a constructor in an interface?

Below is a question about defining a constructor signature in the TypeScript (Javascript) interface, although it turned out to be unavailable in the end. However, this is possible in objective-c and that it would be nice to have it elsewhere.

I have a set of classes of data objects and they will all be used through a common constructor with a json string argument. Since I chose TypeScript as a tool that has a compiler and helps me find errors and problems earlier, how can I define a constructor in an interface and then implement it in a class?

interface IParsable {

  //constructor(json : string);
  new (json : string);
}

class UserObject implements IParsable {

constructor(json : string) {

   //...
}

      

The code works, but the compiler shows me the error "error TS2420: Class 'UserObject' does not correctly implement interface" IParsable "." If I use "constructor" instead of the new one in the interface, I get "The constructor of methods from interaface IParsable is not implemented".

UPDATE . In objective-c, an object can be created using two approaches:

First approach :

UserObject *userObject = [[UserObject alloc] init]; 

      

Object creation consists of two methods. Alloc - allocates the required memory, and init is the name of the default constructor. Constructors are just like regular methods in objective-c and have their own names. So if you need a custom constructor with parameters, you just define a new method, like initWithJson: (NSString *) json. So you can define whatever you want in the interface and enforce the contract.

Second approach :

UserObject *userObject = [UserObject new]; 

      

new is a reserved word, however it actually does alloc + init and you cannot use your custom constructor. Therefore, it is recommended to use alloc + init so that you can always replace it with your own constructor method like alloc + initWithJson if you need.

As it turns out, there is no way to do this even in java or C #. I always thought that these languages ​​are much more standardized and well thought out from an OOP perspective, although this little thing is better done in objective-c.

+3


source to share


2 answers


The clause extends

defines the behavior of an instance of the class, not its constructor function. The constructors themselves are not part of the class instance. Basically, you are saying that the instance UserObject

(the result of calling new

on it) can itself be called new

, which is not the case:

var x = new UserObject();
var y = new x(); // Nonsense, of course

      



There is currently no direct syntax in TypeScript to indicate that a constructor function UserObject

conforms to an interface IParsable

. You can use this as a workaround:

class UserObject { ... }
UserObject === <IParsable>undefined;

      

+1


source


TypeScript is structurally typed, so you can get all the validation you need without requiring a keyword implements

for the class.

The example below validates the arguments passed to the constructor IParsable

(inside the function example

). You also cannot pass an argument to a function example

that does not satisfy the interface IParsable

, i.e. It must accept a string argument (or no argument at all).



I have highlighted three errors that the compiler will catch.

interface IParsable {
    new (json: string);
}

class ExampleOne {
    constructor(json: string) {

    }
}

class ExampleTwo {
    constructor(json: string) {

    }
}

class ExampleThree {
    constructor(arg: number) {

    }
}

function example(obj: IParsable) {
    // Error - doesn't pass string arg
    //return new obj();

    // Error - wrong argument type
    //return new obj(1);

    return new obj('{ a: "b"}');

}

example(ExampleOne);
example(ExampleTwo);

// Error - Doesn't satisfy IParsable
//example(ExampleThree);

      

+1


source







All Articles