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

TypeScript动态泛型:如何根据id值自动推导defaultValue属性类型

根据对象字段自动推导关联字段类型的PropConfig实现

问题背景

需求为配置对象的defaultValue字段可根据同对象内id字段的取值,自动匹配对应的类型约束。
初始实现需要手动传入第二个泛型参数才能获得正确的类型校验,写法如下:

type User = {
  name: string;
  age: number;
};

type PropConfig<T, K extends keyof T> = {
  id: K;
  label: string;
  defaultValue: T[K];
};

// 需要手动传入第二个泛型参数'age'才能校验defaultValue类型
const config: PropConfig<User, 'age'> = {
  id: 'age',
  label: 'Age',
  defaultValue: 18,
};

尝试给第二个泛型加默认值的写法会出现类型校验失效问题,无法实现自动推导:

type PropConfig<T, K = keyof T> = {
  id: K;
  label: string;
  defaultValue: T[K]; // defaultValue会被推导为所有字段值的联合类型,无法精准匹配
};

const config: PropConfig<User> = {
  id: 'age',
  label: 'Age',
  defaultValue: 18,
};

原有写法失效原因

给泛型K设置默认值K = keyof T时,如果不手动传入K,TS会直接将K填充为keyof T即目标类型所有字段名的联合类型(对上述User类型来说就是'name' | 'age'),此时defaultValue的类型会被推导为T[keyof T]即所有字段值的联合类型(string | number),无法根据对象字面量里实际赋值的id字段做类型收窄,自然无法实现精准校验。

可落地的实现方案

方案1:泛型辅助函数(推荐,适配复杂场景)

TS不会在变量类型标注阶段自动推导未指定的泛型参数,但调用泛型函数时,可以根据传入的参数值自动推导泛型的具体类型,只需要写一个通用的辅助函数即可实现自动推导,不需要额外传第二个泛型。

type User = {
  name: string;
  age: number;
};

type PropConfig<T, K extends keyof T> = {
  id: K;
  label: string;
  defaultValue: T[K];
};

// 定义泛型辅助函数,K的类型由传入的配置对象自动推导
function definePropConfig<T extends object, K extends keyof T>(config: PropConfig<T, K>) {
  return config;
}

// 使用时仅需传入第一个泛型参数,id和defaultValue自动做类型绑定
const ageConfig = definePropConfig<User>({
  id: 'age',
  label: 'Age',
  defaultValue: 18, // 类型校验为number,传字符串会直接报错
});

const nameConfig = definePropConfig<User>({
  id: 'name',
  label: 'Name',
  defaultValue: 'Zhang San', // 类型校验为string,传数字会直接报错
});

方案2:映射类型生成联合类型(无额外函数,轻量场景适用)

如果不想引入额外的辅助函数,可以通过映射类型遍历目标类型的所有key,生成每个key对应的合法配置类型,最后通过索引取所有配置类型的联合。TS校验对象字面量时,会自动根据id字段匹配对应的类型分支,实现类型收窄。

type User = {
  name: string;
  age: number;
};

// 遍历T的所有key生成对应配置,最后取联合类型
type PropConfig<T> = {
  [K in keyof T]: {
    id: K;
    label: string;
    defaultValue: T[K];
  }
}[keyof T];

// 直接标注类型即可,不需要传第二个泛型
const ageConfig: PropConfig<User> = {
  id: 'age',
  label: 'Age',
  defaultValue: 18, // 正确,类型为number
};

const nameConfig: PropConfig<User> = {
  id: 'name',
  label: 'Name',
  defaultValue: 'Zhang San', // 正确,类型为string
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:39:35