You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使带可选泛型参数的CalendarDate类通过TypeScript类型检查?

解决方案

核心问题在于泛型参数约束与默认值不匹配:当泛型被实例化为非undefined的子类型时,默认值undefined无法赋值给该类型。以下是具体修改方案:

1. 调整泛型定义,设置默认类型

给泛型参数添加默认值undefined,明确未指定时的类型:

class CalendarDate<
  DAY extends number | undefined = undefined,
  NTH extends string | undefined = undefined,
  MIL extends number | undefined = undefined
> extends Date {

2. 构造函数参数添加类型断言

给可选参数的默认值添加类型断言,让TypeScript认可默认值与泛型类型的兼容性:

constructor(
  public date: Date,
  public day: DAY = undefined as DAY,
  public nth: NTH = undefined as NTH,
  public milliseconds: MIL = undefined as MIL,
) {
  super(date);
}

3. 明确Getter的返回泛型类型

在各个getter中,明确返回的CalendarDate实例的泛型参数,确保链式调用后属性类型正确:

get $day(): CalendarDate<number, NTH, MIL> {
  const day = this.getDate();
  return new CalendarDate(this, day, this.nth, this.milliseconds);
}

get $nth(): CalendarDate<number, string, MIL> {
  const self = this.$day;
  const nth = getDateNth(self.day);
  return new CalendarDate(self, self.day, nth, self.milliseconds);
}

get $milliseconds(): CalendarDate<DAY, NTH, number> {
  const milliseconds = this.valueOf();
  return new CalendarDate(this, this.day, this.nth, milliseconds);
}

4. 补充getDateNth函数实现

示例实现一个生成日期序数后缀的函数(可根据实际需求调整):

function getDateNth(day: number): string {
  if (day >= 11 && day <= 13) return `${day}th`;
  switch (day % 10) {
    case 1: return `${day}st`;
    case 2: return `${day}nd`;
    case 3: return `${day}rd`;
    default: return `${day}th`;
  }
}

修改后的完整代码

function getDateNth(day: number): string {
  if (day >= 11 && day <= 13) return `${day}th`;
  switch (day % 10) {
    case 1: return `${day}st`;
    case 2: return `${day}nd`;
    case 3: return `${day}rd`;
    default: return `${day}th`;
  }
}

class CalendarDate<
  DAY extends number | undefined = undefined,
  NTH extends string | undefined = undefined,
  MIL extends number | undefined = undefined
> extends Date {
  constructor(
    public date: Date,
    public day: DAY = undefined as DAY,
    public nth: NTH = undefined as NTH,
    public milliseconds: MIL = undefined as MIL,
  ) {
    super(date);
  }

  get $day(): CalendarDate<number, NTH, MIL> {
    const day = this.getDate();
    return new CalendarDate(this, day, this.nth, this.milliseconds);
  }

  get $nth(): CalendarDate<number, string, MIL> {
    const self = this.$day;
    const nth = getDateNth(self.day);
    return new CalendarDate(self, self.day, nth, self.milliseconds);
  }

  get $milliseconds(): CalendarDate<DAY, NTH, number> {
    const milliseconds = this.valueOf();
    return new CalendarDate(this, this.day, this.nth, milliseconds);
  }
}

const d = new CalendarDate(new Date());
console.log(d.$day.day); // 类型为number,非undefined
console.log(d.$nth.nth); // 类型为string,非undefined
console.log(d.$milliseconds.milliseconds); // 类型为number,非undefined

关键说明

  • 泛型默认类型确保:未指定参数时属性为undefined,指定后属性为对应非空类型。
  • 类型断言undefined as DAY解决了默认值与泛型子类型的兼容性问题。
  • Getter明确返回泛型类型,确保链式调用后属性类型被正确推导。

内容的提问来源于stack exchange,提问作者ThomasReggi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 11:35:25