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

TypeScript如何排除父类属性,实现仅接受子类扩展属性的泛型函数

解决泛型函数仅接受子类扩展属性的问题

首先定义基础类和子类示例:

class BaseClass {
  hasId: boolean;
  constructor() {
    this.hasId = false;
  }
}

class Genial extends BaseClass {
  name: string;
  age: number;
  constructor() {
    super();
    this.name = "";
    this.age = 0;
  }
}

你遇到的Type 'K' cannot be used to index type 'T'错误,是因为直接用Exclude<keyof T, keyof BaseClass>作为泛型约束时,TypeScript无法明确推断出K一定是T的有效索引(尽管逻辑上成立)。改用Omit工具类型可以更清晰地定义子类独有的属性集合,解决这个问题。

正确实现方式

// 提取子类独有的属性类型
type SubclassOnlyProps<T extends BaseClass> = Omit<T, keyof BaseClass>;

function getSubclassProp<T extends BaseClass>(
  obj: T,
  prop: keyof SubclassOnlyProps<T>
): SubclassOnlyProps<T>[typeof prop] {
  return obj[prop];
}

测试验证

const genialInstance = new Genial();

// 合法调用:仅允许子类扩展的属性
getSubclassProp(genialInstance, "name"); // 返回 string 类型
getSubclassProp(genialInstance, "age");  // 返回 number 类型

// 非法调用:父类属性会直接报错
getSubclassProp(genialInstance, "hasId"); // 类型错误,符合预期

替代写法(直接在函数泛型中约束)

如果不想单独定义类型别名,也可以直接在函数泛型中使用Omit:

function getSubclassProp<T extends BaseClass, K extends keyof Omit<T, keyof BaseClass>>(
  obj: T,
  prop: K
): Omit<T, keyof BaseClass>[K] {
  return obj[prop];
}

原理说明

  • Omit<T, keyof BaseClass>会生成一个新类型,仅包含T中不属于BaseClass的属性,确保这个类型的所有键都是子类独有的。
  • 将K约束为keyof Omit<T, keyof BaseClass>,就严格限制了函数参数只能是子类的扩展属性,同时TypeScript能明确识别K是T的有效索引,避免了2536错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:45:59