I'm reading TS documentation, when I read More on Functions, I don't understand the code below, how to use it in actual development. Are there any examples?
interface CallOrConstruct {
new (s: string): Date;
(n?: number): number;
}
I'm reading TS documentation, when I read More on Functions, I don't understand the code below, how to use it in actual development. Are there any examples?
interface CallOrConstruct {
new (s: string): Date;
(n?: number): number;
}
What you see here is a single object that has different behavior depending on whether you call it with new
. This is something Javascript is capable of doing, but can lead to confusing code; you'll probably see that kind of signature only very infrequently, or when adapting a very old or flexible Javascript library for Typescript usage.
(Technically, the behavior doesn't have to be different: Sensible objects might be callable with or without new
with the same overall behavior, and would require both call and construct signatures. However, this kind of deliberate flexibility is still unusual. Thanks @kaya3!)
Your snippet appears in More on Functions under the text:
Some objects, like JavaScript’s
Date
object, can be called with or withoutnew
. You can combine call and construct signatures in the same type arbitrarily:
This is a reference to the built-in Date object, which has this text on MDN:
Date()
When called as a function, returns a string representation of the current date and time, exactly as
new Date().toString()
does.
new Date()
When called as a constructor, returns a new
Date
object.
console.log(typeof Date()) // string
console.log(typeof new Date()) // object
As said above, it is very uncommon that a single Function object will serve both purposes: You'll usually see a function/class deliberately called as one or the other, but not both. However, because it is possible to do in Javascript (and even done in built-in objects) it is important for TypeScript to be able to represent an object that works in both call styles.
interface CallOrConstruct {
new (s: string): Date; // construct
(n?: number): number; // call
}
// construct
let object: Date = new CallOrConstruct("optional string s");
// call
let myNumber: number = CallOrConstruct(/* n= */ 42);
You probably won't need to ever type out an interface like this, especially if you use class
and constructor
for classes and function
(or other normal function declarations) for your functions. You'll only need to do so if you're trying to declare types TypeScript doesn't understand (as in a .d.ts
TypeScript declarations file for an external Javascript library) or if you're trying to write a clever and confusing TypeScript object that can used in both ways. Speaking for myself, I haven't had a reason to write my own declaration like this, though I've read a few in libraries and their typings.