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

在泛型内使用索引访问类型时避免联合类型推断

解决TypeScript中泛型接口根据key值推断render函数签名的问题

你的核心问题是联合类型无法关联key和render的类型关系,导致指定key时,render参数被推断为所有属性类型的联合。可以通过分布式联合类型实现key与render参数类型的绑定,让TypeScript根据具体key值精确推断类型。

修正后的类型定义

import type { JSX } from "react";

interface BaseColumnDefinition<T extends Record<string, any>> {
  label?: string;
}

// 无key的列定义:render接收完整的T对象
interface KeylessColumnDefinition<T extends Record<string, any>> extends BaseColumnDefinition<T> {
  key?: undefined;
  render: (value: T) => JSX.Element;
}

// 针对单个key的有key列定义:泛型K绑定具体的key,render参数对应T[K]
type KeyedColumnDefinition<T extends Record<string, any>, K extends keyof T> = BaseColumnDefinition<T> & {
  key: K;
  render: (value: T[K]) => JSX.Element;
};

// 生成包含所有key类型的联合类型,再合并无key类型
type ColumnDefinition<T extends Record<string, any>> =
  | KeylessColumnDefinition<T>
  | { [K in keyof T]: KeyedColumnDefinition<T, K> }[keyof T];

测试验证

type TestData = { name: string; id: string; value: number };

// 无key场景:render参数正确推断为完整TestData类型
const definitionWithoutKey: ColumnDefinition<TestData> = {
  label: "Name",
  render: (value) => <></>,
};

// 有key场景:key为"value"时,render参数自动推断为number类型
const definitionWithKey: ColumnDefinition<TestData> = {
  label: "Name",
  key: "value",
  render: (value) => <></>,
};

// 类型校验生效:key为"name"时,render参数传number会报错
const definitionWithWrongType: ColumnDefinition<TestData> = {
  label: "Name",
  key: "name",
  render: (value: number) => <></>, // ❌ 类型错误:value应为string
};

原理说明

  • 原代码中KeyedColumnDefinition用T[this["key"]]无法在联合类型中关联key和render的类型,因为TypeScript会将联合类型的成员视为独立个体,无法跟踪跨成员的关联。
  • 新方案通过映射类型{ [K in keyof T]: KeyedColumnDefinition<T, K> }[keyof T],为每个key生成单独的类型分支,最终形成一个包含所有key对应类型的联合。当TypeScript匹配到具体的key值时,会自动选中对应的分支,从而精确推断render的参数类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 22:50:16