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 });
核心原理说明
- 泛型参数捕获:通过
setConfig<K extends string>捕获传入的items数组的元素类型(比如"a"|"b"|"c"这种联合类型)。 - 类型绑定:
setCallback的回调参数类型直接绑定到泛型K,确保回调函数里的config结构完全匹配传入的items。 - 全局变量的类型兼容:全局的
config和callback用宽泛类型定义,但实际赋值时会被更具体的泛型类型约束,保证后续操作的类型安全。
内容的提问来源于stack exchange,提问作者K..
相关产品推荐
相关产品推荐

