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

TypeScript:通过泛型键从对象获取正确的值类型

问题描述

我想编写一个简单的查询构建器,让实体的所有类型都能正确转换。例如,使用equalsTo过滤name字段时,只允许传入字符串作为值;过滤age字段时,只允许传入数字作为值。但目前value可以是Dogs类型的任意值,不符合需求,请问是否可以实现这一功能?

原代码如下:

class Dogs {
    name!: string;
    age!: number;
    alive!: boolean;
}
interface QueryBuilder<O extends object, F extends keyof O = keyof O> {
    equalsTo: (fieldName: F, value: O[F]) => boolean;
}
const queryBuilder = <O extends object>(): QueryBuilder<O> => ({
    equalsTo: (fieldName, value) => true 
})
const qb = queryBuilder<Dogs>();
qb.equalsTo("name", 1); // 应该抛出错误:仅允许字符串作为值
qb.equalsTo("age", "Rex"); // 应该抛出错误:仅允许数字作为值
解决方案

可以实现,核心是把equalsTo改成方法级别的泛型,让TypeScript在每次调用方法时,根据传入的字段名动态推断对应的值类型,而不是提前固定泛型参数。

修改后的代码:

class Dogs {
    name!: string;
    age!: number;
    alive!: boolean;
}

// 移除QueryBuilder接口上的F泛型,把泛型移到equalsTo方法上
interface QueryBuilder<O extends object> {
    equalsTo: <F extends keyof O>(fieldName: F, value: O[F]) => boolean;
}

const queryBuilder = <O extends object>(): QueryBuilder<O> => ({
    equalsTo: (fieldName, value) => true 
})

const qb = queryBuilder<Dogs>();
qb.equalsTo("name", 1); // ✅ 现在会抛出类型错误:number不能赋值给string
qb.equalsTo("age", "Rex"); // ✅ 现在会抛出类型错误:string不能赋值给number

原理说明

原来的代码把F作为QueryBuilder接口的泛型参数,这会让O[F]变成所有字段类型的联合类型(比如string | number | boolean),所以value可以接收任意类型的值。

改成方法级泛型后,每次调用equalsTo时,TypeScript会根据传入的fieldName推断出具体的F(比如传入"name"时,F就是"name"),此时O[F]就精确对应该字段的类型(string),从而严格限制value的类型必须匹配字段类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 08:06:28