Call a new date with the union type "number | string"

Consider the following snippet (see also TS Playground ):

var nr: number = 123456; var str: string = "2015-01-01T12:00:00"; var both: number | string = 123456; var myDate: Date; myDate = new Date(nr); myDate = new Date(str); myDate = new Date(both); // <-- Compile error 

This final line gives a compiler error:

Argument of type number | string number | string not assigned to a parameter of type 'string'. The type 'number' is not assigned to the type 'string'.

However, since there is a Date(...) constructor for both types, I would assume that the above would work.

I can get around the problem because there is another constructor with the any parameter:

 myDate = new Date(<any> both); 

But what if this constructor was not, for example. if this scenario occurred in my own class?

Is there a way to make this work correctly? Or is it a type of association that describes the smell of design, indicating that my definitions need to be changed?

I checked the TS Handbook , but there is no section on connection types in it. I tried to solve it myself, but I did not pass the <any> trick mentioned above. I looked at suggested duplicates and similar questions on SO, but have not yet found an answer.

+5
source share
2 answers

You can extend the date constructor interface to support this; probably not the nicest solution, but it seems to work ...

 interface DateConstructor { new (value: number | string): Date; } var nr: number = 123456; var str: string = "2015-01-01T12:00:00"; var both: string | number = "123456"; var myDate: Date; myDate = new Date(nr); myDate = new Date(str); myDate = new Date(both); // <-- No more compile error 

I think union types are considered first-class citizens in TypeScript, that is, for example: string | number string | number is a native type that can be assigned a string or number . In this regard, value: string and value: number do not match a signature of type value: string | number value: string | number - so it makes sense to extend the DateConstructor to support this.

+4
source

This was discussed in the Typescript github project.

https://github.com/Microsoft/TypeScript/issues/1805

To summarize, it would be nice if this work was in simple situations, like what you presented, but in more complex situations it falls apart.

Essentially, the overload set was used to create information linking argument type 1 to argument type 2 (and it can also be used to bind to the return type). With a union type, this information is lost, and any combination of argument types becomes allowed.

Their suggestion is to have coding standards that say that function types should use union types rather than overloads.

See # 6735 - we discussed, and our plan is to mitigate this by providing a TS Lint rule and a guide in which you should never write a series of overloads that have an equivalent representation in union types.

Somehow, making this work as part of resolving signature overloading is simply too complicated.

+3
source

Source: https://habr.com/ru/post/1245483/


All Articles