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

使用keyof创建的类型无法索引原类型的TypeScript问题

解决TypeScript联合类型下的索引类型报错问题

你遇到的问题是因为TypeScript对联合类型的索引处理比较严格:当T是User | House的子集时,T['data']会被解析成User['data'] | House['data']的联合类型。虽然你的泛型已经约束了K是当前T['data']的键,但TypeScript无法确定这个K能同时适用于联合类型中的所有成员,所以抛出了索引不兼容的错误。

给你两种可行的解决方法:

方法一:类型断言(快速解决)

直接把obj.data断言为T['data'],明确告诉TypeScript当前的obj.data就是对应T的data类型,这样就能正常索引了:

interface User {
  data: {
    id: number;
    name: string;
  }
}
interface House {
  data: {
    number: number;
    street: string;
  }
}
type Obj = User | House;

function getProperty<
  T extends Obj,
  K extends keyof T['data']
>(obj: T, key: K): T['data'][K] {
  // 添加类型断言消除报错
  return (obj.data as T['data'])[key];
}

const user: User = { data: { id: 1, name: "Alice" }};
const house: House = { data: { number: 2, street: "First" }};

const userName = getProperty(user, "name"); // 类型推断为string
const houseNumber = getProperty(house, "number"); // 类型推断为number

方法二:重构泛型约束(更优雅的长期方案)

把带data属性的结构抽成通用泛型接口,让函数直接针对这个通用结构做约束,避免联合类型带来的歧义:

// 定义通用的带data属性的类型
interface WithData<D> {
  data: D;
}

// 原有类型基于通用接口定义
interface User extends WithData<{ id: number; name: string }> {}
interface House extends WithData<{ number: number; street: string }> {}

// 重构后的工具函数
function getProperty<D, K extends keyof D>(obj: WithData<D>, key: K): D[K] {
  return obj.data[key]; // 此处无类型报错
}

const user: User = { data: { id: 1, name: "Alice" }};
const house: House = { data: { number: 2, street: "First" }};

const userName = getProperty(user, "name");
const houseNumber = getProperty(house, "number");

这种方式不仅解决了当前的报错,还让工具函数的复用性更强——后续新增类似的带data属性的类型时,只要继承WithData接口就能直接使用getProperty函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 02:22:33