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

如何在TypeScript中用泛型实现精准的字段类型提取?

问题分析与解决方案

原代码的核心问题

  1. 类型信息提前被抹平:你给p标注了Props类型,而Props中的fields是宽泛的Field[],这会把fields里每个元素的具体key字面量和对应value的类型关联丢失,所有key都被拓宽为string,value都变成string | number联合类型。
  2. 泛型参数未绑定具体字段类型:someFn的泛型T约束为Field[],但传入的props是Props类型,导致T只能被推断为Field[],无法获取fields中每个元素的具体类型细节。
  3. 返回类型构造逻辑错误:Rt<ArrayElement<T>>本质是Record<string, string | number>,因为ArrayElement<T>是Field类型,它的value就是string | number,所以所有键对应的值都会是这个联合类型,无法区分每个键的具体值类型。

解决方案与用到的TypeScript特性

要实现精准的类型提取,需要保留fields中每个元素的键值类型关联,同时通过泛型约束、映射类型和Extract工具类型来构建精准的返回类型。

修改后的代码

interface Field {
    key: string;
    value: number | string;
    required?: boolean;
}

// 让Props变成泛型,保留fields的具体类型
interface Props<F extends readonly Field[]> {
    test: number;
    fields: F;
}

// 从字段数组中推断出精准的键值对类型
type InferFieldRecord<F extends readonly Field[]> = {
    // 遍历数组中所有字段的key字面量
    [K in F[number]['key']]: 
        // 筛选出key等于当前K的字段,提取其value类型
        Extract<F[number], { key: K }>['value']
};

const someFn = <F extends readonly Field[]>(props: Props<F>): InferFieldRecord<F> => {
    return props.fields.reduce(
        (acc, vv) => ({
            ...acc,
            [vv.key]: vv.value,
        }),
        // 断言初始值类型,避免TS推断为空对象
        {} as InferFieldRecord<F>,
    );
};

// 不要给p标注Props类型,让TS自动推断fields的具体元素类型
const p = {
    test: 1,
    fields: [
        { key: 'name', value: 'John' },
        { key: 'age', value: 30 },
    ],
};

const r = someFn(p);

console.log(r.name); // 类型为string
console.log(r.age); // 类型为number

关键特性说明

  • 泛型约束:通过F extends readonly Field[]让泛型F绑定到fields的具体数组类型,保留每个元素的key字面量和value类型信息。
  • 映射类型:[K in F[number]['key']]遍历数组中所有字段的key,生成对应对象的键。
  • Extract工具类型:Extract<F[number], { key: K }>从数组元素的联合类型中筛选出key匹配当前K的字段,确保每个键对应的值类型是精准的,而非联合类型。
  • 类型断言:给reduce的初始值{}断言为InferFieldRecord<F>,解决空对象与目标类型的兼容性问题。

额外优化:使用as const锁定字面量类型

如果需要强制fields中的key和value保持字面量类型(避免TS自动拓宽类型),可以给fields添加as const:

const p = {
    test: 1,
    fields: [
        { key: 'name', value: 'John' },
        { key: 'age', value: 30 },
    ] as const,
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 14:32:45