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

TypeScript如何为泛型对象的每个键实现类型推断与约束

TypeScript泛型配置类型的类型推断实现问题

首先定义了如下泛型类型:

type Value<T = any> = {
   component: ComponentType<T>,
   getDuration: (input: T) => void
}

原本的配置类型定义为:

type ConfigType = {
    [k: string]: Value
}

需求如下:

  • 为每个配置项添加类型约束,禁止创建无效配置:比如component接收Prop1类型参数,但getDuration接收Prop2类型参数(Prop1≠Prop2)的情况必须报错;两者参数类型一致的配置则有效。
  • 通过键访问配置时,TypeScript需要自动推断出具体的泛型类型,而非any。例如config.Default.component要推断为ComponentType<Prop1>,而非ComponentType<any>。

曾尝试以下写法但无效:

type ConfigTemplates<Config extends { [k: string]: Value<unknown> }> =
Config extends Record<string, Value>
? {
    [templateName in string]: Config[templateName] extends Value<
      infer Props
    >
      ? Value<Props>
      : never;
  }
: never;

解决方案

方案1:泛型配置类型+satisfies关键字

让ConfigType成为泛型类型,为每个键单独绑定对应的泛型参数,再通过satisfies约束配置结构:

import type { ComponentType } from 'react'; // 假设ComponentType来自React

type Value<T = any> = {
  component: ComponentType<T>,
  getDuration: (input: T) => void
};

// 泛型配置类型,每个键对应专属的Value<T>
type ConfigType<T extends Record<string, unknown>> = {
  [K in keyof T]: Value<T[K]>
};

// 示例Props类型
type Prop1 = { id: number };
type Prop2 = { name: string };
type Prop3 = { age: number };

// 创建配置,自动推导类型,不匹配会报错
const config = {
  Default: {
    component: (props: Prop1) => null,
    getDuration: (props: Prop2) => {} // ❌ 类型不匹配,TypeScript报错
  },
  Template1: {
    component: (props: Prop3) => null,
    getDuration: (props: Prop3) => {} // ✅ 类型匹配,正常通过
  }
} satisfies ConfigType<{
  Default: Prop1,
  Template1: Prop3
}>;

// 类型推断正常
const defaultComp = config.Default.component; // 类型为ComponentType<Prop1>
const template1GetDuration = config.Template1.getDuration; // 类型为(input: Prop3) => void

方案2:工具函数自动推导

如果不想手动声明泛型参数,可以用工具函数来自动推导并约束类型:

import type { ComponentType } from 'react';

type Value<T = any> = {
  component: ComponentType<T>,
  getDuration: (input: T) => void
};

// 工具函数,用于约束配置结构并自动推导类型
function createConfig<T extends Record<string, unknown>>(config: {
  [K in keyof T]: Value<T[K]>
}) {
  return config;
}

// 示例Props类型
type Prop1 = { id: number };
type Prop2 = { name: string };
type Prop3 = { age: number };

// 使用工具函数创建配置
const config = createConfig({
  Default: {
    component: (props: Prop1) => null,
    getDuration: (props: Prop2) => {} // ❌ 类型不匹配,直接报错
  },
  Template1: {
    component: (props: Prop3) => null,
    getDuration: (props: Prop3) => {} // ✅ 类型匹配
  }
});

// 自动推断出具体类型
config.Default.component; // ComponentType<Prop1>
config.Template1.getDuration; // (input: Prop3) => void

原写法无效的原因

你之前的ConfigTemplates类型通过条件类型试图推断参数,但它的索引签名是[templateName in string],会丢失具体键名和对应泛型参数的关联信息,最终只能得到一个模糊的string索引类型,无法实现精确的类型约束和推断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 22:57:46