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

TypeScript中多函数共用同一泛型类型

实现类型安全的泛型setConfig与自动类型推断

当然可以做到!我们可以通过给setConfig添加泛型参数,让TypeScript自动捕获传入的items类型,进而推断出回调函数里config的类型,同时还能满足你在其他位置添加事件监听、修改config且保留类型安全的需求。

基础实现方案

首先我们重构代码,加入泛型定义和类型约束:

// 先定义getData的类型(可根据实际业务逻辑调整)
function getData(key: string): string {
  return `data_${key}`;
}

// 用宽泛类型定义全局的config和callback,后续会被泛型约束覆盖
let config: { items: Record<string, ReturnType<typeof getData>> } | undefined;
let callback: ((config: typeof config) => void) | undefined;

// 给setConfig添加泛型参数K,捕获items的元素类型(联合类型)
function setConfig<K extends string>(c: { items: readonly K[] }) {
  // 初始化config,用类型断言指定为对应泛型的Record类型
  config = { items: {} as Record<K, ReturnType<typeof getData>> };
  
  for (const i of c.items) {
    config.items[i] = getData(i);
  }

  return {
    // setCallback的回调参数类型绑定到泛型K,自动推断config结构
    setCallback: (cb: (config: { items: Record<K, ReturnType<typeof getData>> }) => void) => {
      callback = cb;
    }
  };
}

// 使用示例:自动推断类型
const { setCallback } = setConfig({ items: ["a", "b", "c"] });
setCallback(function myCallback(config) {
  // 这里config.items会自动推断出包含"a"|"b"|"c"三个键,值类型为string
  console.log(config.items["a"]);
  console.log(config.items["b"]);
  console.log(config.items["c"]);
  
  // 尝试访问不存在的键(比如"d")会直接触发TS报错,保证类型安全
  // console.log(config.items["d"]); // 错误:类型“"d"”的参数不能赋给类型“"a" | "b" | "c"”的参数
});

// 在其他位置添加事件监听(类型安全)
// 假设x是某个DOM元素或事件发射器
const x = document.createElement("div");
x.addEventListener("someEvent", () => {
  if (callback && config) {
    callback(config);
  }
});

// 修改config的示例(类型安全)
if (config) {
  config.items["a"] = "updated_data_a"; // 必须符合getData的返回类型(string)
  // config.items["a"] = 123; // 错误:类型“number”不能赋给类型“string”
  // config.items["d"] = "test"; // 错误:类型“"d"”的参数不能赋给类型“"a" | "b" | "c"”的参数
}

进阶:动态返回类型的getData

如果你的getData会根据不同key返回不同类型,我们可以给getData也添加泛型,让类型推断更精准:

// 给getData添加泛型,根据key返回不同类型
function getData<K extends string>(key: K): 
  K extends "a" ? number : 
  K extends "b" ? boolean : 
  string 
{
  return (key === "a" ? 123 : key === "b" ? true : `data_${key}`) as any;
}

// 其余代码无需修改,TypeScript会自动推断config的类型
setConfig({ items: ["a", "b", "c"] }).setCallback((config) => {
  console.log(config.items["a"]); // 类型推断为number
  console.log(config.items["b"]); // 类型推断为boolean
  console.log(config.items["c"]); // 类型推断为string
});

核心原理说明

  1. 泛型参数捕获:通过setConfig<K extends string>捕获传入的items数组的元素类型(比如"a"|"b"|"c"这种联合类型)。
  2. 类型绑定:setCallback的回调参数类型直接绑定到泛型K,确保回调函数里的config结构完全匹配传入的items。
  3. 全局变量的类型兼容:全局的config和callback用宽泛类型定义,但实际赋值时会被更具体的泛型类型约束,保证后续操作的类型安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 20:22:46