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

如何禁止Foo子类重写init方法时返回Promise<any>(Foo非抽象类)

解决方案

泛型约束+any类型拦截

修改基类Foo,引入泛型参数并配合工具类型,从根源上禁止子类将init的返回类型设为Promise<any>:

// 工具类型:排除any类型,若传入any则返回never
type NotAny<T> = T extends any ? (unknown extends T ? never : T) : T;

class Foo<T = void> {
  async init(): Promise<NotAny<T>> {
    return undefined as NotAny<T>;
  }
}

// 合法示例:返回Promise<number>
class Bar extends Foo<number> {
  async init(): Promise<number> {
    return 3;
  }
}

// 合法示例:返回Promise<string>
class Baz extends Foo<string> {
  async init(): Promise<string> {
    return "hello";
  }
}

// 非法示例:尝试返回Promise<any>,TypeScript会直接报错
class InvalidBar extends Foo<any> {
  async init(): Promise<any> {
    return {};
  }
}

核心逻辑

  • NotAny<T>通过条件类型判断:如果T是any,则返回never,否则返回T。当子类指定泛型为any时,基类的init返回类型会变为Promise<never>,与子类的Promise<any>类型不兼容,触发类型错误。
  • 泛型参数默认值设为void,完全保留基类原有行为,不需要修改Foo的业务逻辑。

备选方案:返回类型协变+类型校验

如果不想引入泛型,也可以利用TypeScript的返回类型协变特性,配合工具类型限制:

class Foo {
  async init(): Promise<unknown> {
    return undefined;
  }
}

// 工具类型:拦截Promise<any>
type ForbidAnyPromise<T> = T extends Promise<any> ? never : T;

// 合法示例:返回Promise<number>(协变兼容Promise<unknown>)
class Bar extends Foo {
  async init(): Promise<number> {
    return 3;
  }
}

// 非法示例:返回Promise<any>会触发类型错误
class InvalidBar extends Foo {
  async init(): ForbidAnyPromise<Promise<any>> {
    return {};
  }
}

核心逻辑

  • TypeScript允许返回类型协变,Promise<number>/Promise<string>等可以兼容基类的Promise<unknown>,但Promise<any>会被ForbidAnyPromise映射为never,强制子类无法使用该类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 11:33:20