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

问题描述 投票:0回答:4

如何正确定义 Date 子类的构造函数(typescript 4.1.3)?

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)
         */         
    }
}

但这会导致超级调用中出现编译错误:

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 并保持类型安全(尽可能)?

备注:

  • 这里是 typescript Playground 示例的链接
  • 这只是一些测试代码,在生产版本中,我在构造函数中有更多代码
  • 我想要一个适用于类的解决方案(即不要弄乱原型等)
javascript typescript datetime constructor-overloading
4个回答
3
投票

如果您想支持

Date
支持的所有签名,我认为除了分支(或punting)之外您没有太多选择:

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);
        }
    }
}

游乐场链接


¹ (就其价值而言,我不认为你,尽管你可能很想这样做。与

Array
Promise
不同,我不认为
Date
构造函数在任何地方被调用标准库)


2
投票

您需要添加一些检查并针对每种情况调用适当的父构造函数:

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)
        }
    }

工作游乐场链接


2
投票

你今天可以做这样的事情:

class MyDate extends Date {
  constructor(...args: ConstructorParameters<typeof Date>) {
    super(...args)
  }
}

0
投票

我遇到了同样的问题,并像这样实现它修复了所有 TS 错误:

class MyDate extends Date {
  constructor();

  constructor(value: number | string);

  constructor(
    year: number,
    month: number,
    date?: number,
    hours?: number,
    minutes?: number,
    seconds?: number,
    ms?: number,
  );

  constructor(
    ...args: [] | [number | string] | [number, number, number?, number?, number?, number?, number?]
  ) {
    if (args.length === 0) {
      super();
    } else if (args.length === 1) {
      super(args[0]);
    } else {
      super(...args);
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.