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

TypeScript泛型类方法返回新实例时泛型类型推导失效问题

问题根因

类方法返回新Schema实例时未显式指定泛型参数,TypeScript 无法从运行时对象操作逻辑反向推导准确类型:

  • pick方法中reduce初始值为空对象{},TS默认推导其类型为{},最终返回实例的泛型参数被推导为{},keyof {}得到never类型,因此调用pick传入任何字符串属性名都会报类型不匹配错误
  • 原set方法的key、value参数标注为string/any,返回实例的泛型直接退化为Record<string, any>,完全丢失原有属性的类型约束
修正实现

你给出的set方法类型实现是正确的,pick方法只需补充泛型约束,显式指定返回实例的泛型为选中属性的子类型即可,完整修正代码如下:

class Schema<PropType extends Record<string, any>> {
  props: PropType;

  constructor(props: PropType) {
    this.props = props;
  }

  pick<K extends keyof PropType>(...propNames: Array<K>) {
    return new Schema(propNames.reduce(
      (obj, key) => ({ ...obj, [key]: this.props[key] }),
      {} as Pick<PropType, K>
    ));
  }

  set<K extends string, V>(key: K, value: V) {
    return new Schema<PropType & Record<K, V>>({
      ...this.props,
      [key]: value
    });
  }
}

说明:reduce中的as Pick<PropType, K>类型断言是必要的,TypeScript 无法静态验证遍历组装后对象一定包含所有传入的K类型键,需要开发者保证运行时逻辑与类型声明一致,当前实现逻辑符合该要求。

类型验证

修正后所有场景的类型检查均符合预期:

const Person = new Schema({ firstName: 'Fyodor', lastName: 'Dostoevsky' });
Person.pick('firstName'); // 类型校验通过
Person.pick('madeup'); // 正确抛出类型错误

const JustFirst = Person.pick('firstName')
JustFirst.pick('firstName'); // 类型校验通过
JustFirst.pick('lastName'); // 正确抛出类型错误,JustFirst实例不存在lastName属性

const ExtraPerson = Person.set('middleName', 'Mikhailovich');
ExtraPerson.pick('middleName', 'firstName'); // 类型校验通过
ExtraPerson.pick('butNothingIsTyped'); // 正确抛出类型错误,实例不存在该属性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 15:06:08