TypeScript如何实现限制键范围及值类型的自定义MagicType类型
核心实现方案
首先你需要先建立MyType每个取值和对应回调参数类型的映射关系,再基于映射生成MagicType:
// 1. 先定义各类型专属的结果类型 type ResultForA = { a: string }; // 替换为你实际的A类型定义 type ResultForB = { b: number }; // 替换为你实际的B类型定义 type ResultForC = { c: boolean }; // 替换为你实际的C类型定义 // 2. 建立类型字面量到对应结果类型的映射 type TypeResultMap = { A: ResultForA; B: ResultForB; C: ResultForC; }; // 3. MyType可直接从映射键提取,避免重复定义 type MyType = keyof TypeResultMap; // 4. 最终实现MagicType type MagicType = { [K in MyType]?: true | ((result: TypeResultMap[K]) => void); };
效果验证
- 合法场景可以正常通过校验:
const validObj: MagicType = { A: (res) => console.log(res.a), // res会自动推导为ResultForA类型 C: true }; // 未声明B字段属于合法情况
- 非法场景会触发类型报错:
const invalidObj: MagicType = { A: (res: ResultForB) => {}, // 报错:回调参数类型与A不匹配 FOO: true // 报错:FOO不属于允许的键范围 };
原有方案缺陷原因
你之前的方案存在两个问题:
Record<MyType, T>生成的是所有MyType键必填的类型,不符合可选键的要求- 回调类型定义为任意参数的函数,自然无法校验回调参数的类型匹配问题
附加问题解答
可以通过映射直接生成你需要的元组联合类型,不需要手动枚举:
type MyTypePairs = { [K in MyType]: [K, (result: TypeResultMap[K]) => void]; }[MyType];
最终生成的MyTypePairs等价于:
type MyTypePairs = | ['A', (result: ResultForA) => void] | ['B', (result: ResultForB) => void] | ['C', (result: ResultForC) => void];
完全符合你需要的强绑定要求。
内容的提问来源于stack exchange,提问作者J. Hesters
相关产品推荐
相关产品推荐

