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

TypeScript中带类型的泛型键值接口定义问题

解决TypeScript中对象属性内部类型匹配的问题

你遇到的核心问题是:原始接口里的T没有和每个属性绑定,导致无法单独约束每个键的default和fn参数类型一致。下面是两种可行的解决方案:

方法一:泛型映射类型显式约束

首先定义单个属性的通用类型,确保default和fn参数共享同一类型:

// 单个属性的结构,T是default和fn参数的共同类型
type Prop<T> = {
  default: T;
  fn: (val: T) => any;
};

接着用映射类型创建Foo,它会根据你传入的类型映射,为每个键生成对应的类型约束:

// Foo接受一个泛型参数,描述每个键的类型
type Foo<T extends Record<string, unknown>> = {
  [Key in keyof T]: Prop<T[Key]>;
};

现在你可以显式指定每个键的类型,TypeScript会自动检查default和fn的类型是否匹配:

const foo: Foo<{
  key1: string;
  key2: number;
  key3: boolean;
}> = {
  key1: { default: 'foo', fn: (val) => val }, // val自动推断为string
  key2: { default: 42, fn: (val) => val }, // val自动推断为number
  key3: { default: true, fn: (val) => val }, // 如果把val写成string,这里会直接报错
};

方法二:工厂函数自动推断(更便捷)

如果你不想手动声明每个键的类型,可以用工厂函数让TypeScript自动推断,同时保持类型约束:

type Prop<T> = {
  default: T;
  fn: (val: T) => any;
};

type Foo<T extends Record<string, unknown>> = {
  [Key in keyof T]: Prop<T[Key]>;
};

// 工厂函数,用来约束传入的对象结构
function createFoo<T extends Record<string, unknown>>(foo: Foo<T>): Foo<T> {
  return foo;
}

// 直接传入对象,TypeScript自动推断类型并检查匹配
const foo = createFoo({
  key1: { default: 'foo', fn: (val) => val },
  key2: { default: 42, fn: (val) => val },
  key3: { default: true, fn: (val: string) => val }, // 这里会报错:类型'string'不能赋值给类型'boolean'
});

为什么原始写法不生效?

你最初的接口interface Foo { [key: string]: { default: T, fn: (val:T) => any } }存在两个问题:

  1. T未定义,TypeScript无法识别这个类型参数;
  2. 即使定义了T,它也会被视为全局类型——所有属性的default和fn都必须使用同一个T,无法实现每个属性独立的类型匹配。

而上面的方案通过泛型映射,让每个键都拥有独立的类型参数,完美解决了你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:45:40