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

如何让TypeScript函数仅接受映射为特定类型的键?

如何让函数仅接受映射为特定类型的键?

给定以下代码:

type Foo = {
    // 任意类型均可
    foo: number;
    bar: number;
    baz: string;
}

function f<T>(obj: T, key: keyof T) {
    const foo = obj[key] // foo的类型应为number
}

const x: Foo = {foo: 0, bar: 1, baz: "a"}
f(x, "foo") // 合法
f(x, "bar") // 合法
f(x, "baz") // 应报错,因为x["baz"]的类型不是number

尝试过扩展T,但无法关联参数中的键:

function f<T extends {key: number}>(obj: T, key: keyof T) {} // 无效

还尝试提取Foo中类型为number的字段键,但Extract未按预期工作:

function f<T>(obj: T, key: keyof (Extract<T, number>))) {} // 同样无效

这在TypeScript中可行吗?


解决方案

完全可行,通过双重泛型约束即可实现:同时限制键的范围,以及该键对应值的类型。

写法一:双重泛型约束

type Foo = {
    foo: number;
    bar: number;
    baz: string;
}

// 约束K为T的键,且T[K]必须是number类型
function f<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key]; // 返回值类型自动推导为number(符合约束时)
}

const x: Foo = {foo: 0, bar: 1, baz: "a"}
f(x, "foo") // 合法,返回number
f(x, "bar") // 合法,返回number
f(x, "baz") // 报错:类型'"baz"'的参数不能赋给类型'"foo" | "bar"'的参数

写法二:自定义条件类型提取键

如果需要预定义符合条件的键集合,可以用条件类型构造:

// 提取对象T中值类型为U的键
type KeysOfType<T, U> = { [K in keyof T]: T[K] extends U ? K : never }[keyof T]

type Foo = {
    foo: number;
    bar: number;
    baz: string;
}

function f<T>(obj: T, key: KeysOfType<T, number>) {
    const foo = obj[key]; // foo类型为number
}

const x: Foo = {foo: 0, bar: 1, baz: "a"}
f(x, "foo") // 合法
f(x, "bar") // 合法
f(x, "baz") // 报错

为什么之前的尝试无效?

  1. 第一种写法中T extends {key: number}的key是固定字面量,无法和传入的key参数动态关联,约束不生效;
  2. Extract<T, number>用法错误:Extract用于从联合类型中提取成员,不能直接从对象类型中筛选值为特定类型的键。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 10:50:24