如何为扩展 Date 的 class 定义构造函数?

How to define the constructor for a class that extends Date?

如何正确定义 Date (typescript 4.1.3) 的 child-class 的构造函数?

Date 对象的构造函数定义是这样的:

new(): Date;
new(value: number | string): Date;
new(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date;

在我的代码中,我尝试指定:

class MyDate extends Date {
    // overloads copied from DateConstructor
    constructor();
    constructor(value: number | string);
    constructor(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number);
    // constructor impl
    constructor(
        yearOrValue?: number | string, month?: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number
    ) {
        super(yearOrValue, month, date, hours, minutes, seconds, ms);
        /*    ^^^^^^^^^^^
              Argument of type 'string | number | undefined' is not assignable to parameter of type 'number'.
              Type 'undefined' is not assignable to type 'number'.(2345)
         */         
    }
}

但这会导致 super 调用出现编译错误:

Argument of type 'string | number | undefined' is not assignable to parameter of type 'number'.
Type 'undefined' is not assignable to type 'number'.(2345)

如何定义构造函数参数,以便我可以使用原始 Date 对象具有的所有可能性调用 super 并保持类型安全(尽可能)?

备注:

如果您想支持 Date 支持的所有签名,¹ 我认为除了分支(或 )之外您别无选择:

class MyDate extends Date {
    // overloads copied from DateConstructor
    constructor();
    constructor(value: number | string);
    constructor(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number);
    // constructor impl
    constructor(
        yearOrValue?: number | string,
        month?: number,
        date?: number,
        hours?: number,
        minutes?: number,
        seconds?: number,
        ms?: number
    ) {
        if (typeof yearOrValue === "undefined") {
            super();
        } else if (typeof month === "undefined") {
            super(yearOrValue);
        } else {
            // consider an assertion here that `yearOrValue` is a number
            super(yearOrValue as number, month, date, hours, minutes, seconds, ms);
        }
    }
}

Playground link


¹ (就其价值而言,我认为您没有,尽管您可能很想这样做。不像ArrayPromise,我不认为 Date 构造函数在标准库的任何地方被调用)

您需要添加一些检查并为每种情况调用正确的父构造函数:

constructor(
        yearOrValue?: number | string, month?: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number
    ) {
        if (yearOrValue === undefined) {
            super()
        } else if (month === undefined) {
            super(yearOrValue)
        } else if (typeof yearOrValue === 'number') {
            super(yearOrValue, month, date, hours, minutes, seconds, ms)
        }
    }

Working playground link