如何让Opts的requiredKeys支持Values与customParsers的键集合?
TypeScript 泛型实现动态约束 requiredKeys 范围
问题场景
你当前定义了以下接口:
interface Values { height: number; width: number; } interface Opts { requiredKeys: (keyof Values)[]; customParsers: Record<string, (text: string) => unknown>; }
希望requiredKeys能同时接受Values的键名和customParsers中定义的键名,比如:
const opts: Opts = { requiredKeys: [ 'height', // 合法:属于Values的键 'foo', // 不合法:既不是Values的键,也未在customParsers中定义 'x', // 合法:在customParsers中已定义 ], customParsers: { x: text => parseInt(text), }, };
直接把requiredKeys改成(keyof Opts['customParsers'] | keyof Values)[]无效,需要通过泛型实现动态约束。
解决方案
使用泛型捕获customParsers的具体键名,让requiredKeys的类型与customParsers的键名动态关联:
interface Values { height: number; width: number; } // 用泛型T约束customParsers的结构,同时关联requiredKeys的范围 interface Opts<T extends Record<string, (text: string) => unknown>> { requiredKeys: (keyof Values | keyof T)[]; customParsers: T; }
用法示例
合法场景
// TypeScript会自动推断customParsers的键为'x',因此requiredKeys允许包含'x' const validOpts: Opts<{x: (text: string) => number}> = { requiredKeys: ['height', 'x'], customParsers: { x: text => parseInt(text), }, }; // 也可以省略泛型参数,让TypeScript自动推断 const validOptsAuto = { requiredKeys: ['width', 'y'], customParsers: { y: text => text.length, }, } satisfies Opts<{y: (text: string) => number}>;
非法场景(会触发编译错误)
// 'foo'不在Values的键或customParsers的键中,编译报错 const invalidOpts = { requiredKeys: ['height', 'foo'], customParsers: { x: text => parseInt(text), }, } satisfies Opts<{x: (text: string) => number}>;
原理说明
泛型T会捕获customParsers的具体键名和类型,(keyof Values | keyof T)[]让requiredKeys的元素只能是Values的键或者T的键(也就是customParsers中定义的键),这样TypeScript就能在编译时完成精确的类型检查。
内容的提问来源于stack exchange,提问作者wathhr
相关产品推荐
相关产品推荐

