I have a Typescript project where I'm calling Date inside of a function. I want to use the same function parameters as the constructor from Date which is overloaded:
interface DateConstructor {
new(): Date;
new(value: number | string | Date): Date;
new(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date;
// ...
}
I would like to use the spread operator in order to pass the parameters to the constructor of Date. So my function should hopefully look like that:
function myFn(...args: DateComponents): Date {
return new Date(...args)
}
I'm not actually returning a date in my case, but this is just for testing...
The question is now how to define DateComponents. I successfully implemented the 3 overloaded signatures of DateConstructor separately from each other.
// Case A: No argument provided
interface A {
(): Date;
}
const a: A = function (...args: []): Date {
return new Date(...args);
}
// Case B: 1 argument provided
interface B {
(value: number | string | Date): void;
}
const b: B = function (...args: [number | string | Date]): Date {
return new Date(...args);
}
// Case C: Between 2 and 7 arguments provided
interface C {
(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): void;
}
const c: C = function (...args: [number, number, number?, number?, number?, number?, number?]): Date {
return new Date(...args);
}
So far so good, everything works.
- A: An empty tuple is used to cover the case where no argument is passed
- B: A tuple with one element covers the case where a single number, string or
Dateobject is passed - C: A tuple with 2 mandatory and 5 optional number elements covers the cases where 2-7 arguments are passed
If I try to combined these 3 examples into 1, I get this:
interface D {
(): void;
(value: number | string | Date): void;
(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): void;
}
type DateComponents = [] | [number | string | Date] | [number, number, number?, number?, number?, number?, number?];
const d: D = function (...args: DateComponents): Date {
return new Date(...args); // <-- ERROR: Expected 0-7 arguments, but got 0 or more.
}
I get an error saying that Typescript thinks that more than 7 arguments could be passed into the Date constructor. I do not understand why because my type DateComponents explicitly defines tuples of 0-7 elements.
I could fix this by using some conditions and type assertions, but I'm hoping there is a prettier solution?
See the code in the Playground here
Any idea to fix this? Thanks a lot!