Monday, February 26, 2018

Static and Dynamic Interface Declarations, Constructor Functions

Leave a Comment

I am a little confused about type definitions:

I want a correct Type Definition for this:

   var AClass = function (param) {         this.field = param;     };       var aVariable = new AClass(1); 

I created this, but the compiler complains about AClass being of the wrong type:

interface ATypeStatic {     new(param: number): AType; }  interface AType {     field: number; }  declare var AClass: ATypeStatic; 

looks like I did not fully grasp the correct useage of 'new' in type declararations.


Summary:

I have:

 var AClass = function (param) {     this.field = param; }; 

I want:

A valid Typescript interface that grasps the ability of this function, to create an object with a paramater called 'field' when called with new (which is obviously not the return type of this function).

I don't want:

Anything containig the keyword class - I am working with legacy code here that I ought not to change.

I would accept:

Any documentation hint that explains IF and WHY this is not covered by Typescript.

2 Answers

Answers 1

Your example works, except you don't end up with an AClass, you end up with an AType. You can combine the new and the field into a single interface:

interface AClass {     new(param: number): AClass;     field: number; }  declare var AClass: AClass;  var aVariable = new AClass(1); 

In this example we preserve the name AClass thoughout, and TypeScript knows that you mean the type when you are inside of a type annotation (so it understands the two concepts of AClass.

Alternatively

If you want to place the implementation in the same file... you can dispense with all of this and just have a class:

class AClass {     constructor(public field: number) {     } }  var aVariable = new AClass(1); 

Answers 2

I would say that the most simple way to make your code works in TS is to use "magic" of the any type:

var AClass = function (param: string) {     this.field = param; }; var aVariable = new (AClass as any)(1); 

You may add some typing (if needed) and cast the function to the any type, to make it possible to cast it to a custom interface (IAClassConstructor):

interface IAClass {     field: any; }  interface IAClassConstructor {     new(param: any): IAClass; }  var AClass: IAClassConstructor = (function (param: string) {     this.field = param; } as any);  var aVariable: IAClass = new AClass(1); 

Here is an example on the Playground.

A hint to the answer "Why it's not converted automatically by TS" would be something like: "It's not converted, because functions are not supposed to be used as constructors, and if you want/need to use functions that way, you need to cast them to correct types".

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment