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

React TypeScript:如何约束泛型参数同时保留keyof T类型

解决方案:约束泛型同时保留具体键类型

嘿,这个问题其实挺典型的——既要给泛型加结构约束,又不想丢失具体的类型推断细节。别担心,只需要给泛型参数A加上合适的约束,同时让TypeScript保持对具体键的推断就行,看下面的实现:

// 给ComponentProps的泛型A添加约束:必须是键为string、值为string的对象
interface ComponentProps<A extends Record<string, string>> {
  actions: A;
  onAction(key: keyof A): void;
}

// 组件定义同样给泛型A加上相同约束
function Component<A extends Record<string, string>>(props: ComponentProps<A>) {
  return <div>{/* ... */}</div>;
}

// 使用示例,完全符合你的需求
<Component 
  actions={{ a: 'one', b: 'two' }} 
  onAction={action => {
    // 这里action的类型依然是"a" | "b",没有退化为string!
    console.log(`触发了动作:${action}`);
  }} 
/>;

为什么这能生效?

这里的Record<string, string>和你写的{[key: string]: string}是等价的,它给A设定了结构规则:只能是键为字符串、值为字符串的对象。但关键在于,TypeScript并不会因为这个约束就把A的类型拓宽成宽泛的Record<string, string>——它依然会根据你传入的actions对象,推断出具体的类型(比如{a: string, b: string})。这样一来,keyof A自然就是该对象所有键的联合类型("a" | "b"),完全满足你的要求。

如果有时候你遇到类型意外退化为string的情况,大概率是因为TypeScript的自动类型拓宽(比如当actions被定义为一个单独的变量而不是直接传入组件时),这时候可以给actions加上as const断言来强制保留字面量类型,但在上面的直接传入场景下,完全不需要额外操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:24:14