根据键类型特定值将第二个参数设为可选的TypeScript问题
解决TypeScript函数参数根据键对应类型动态必填的问题
现有如下TypeScript代码:
interface MY_TYPES { 'xyz': string; 'abc': number; 'baz': undefined; } function testIt<T extends keyof MY_TYPES>(key: T, value?: MY_TYPES[T]) { console.log(key); if (value) { console.log(value); } }
当前调用testIt('xyz')时TypeScript不会报错,但我们期望:当MY_TYPES中该键对应类型不是undefined时,必须传入value参数;只有当键对应类型是undefined时,value才可选。
方案一:使用条件类型定义参数列表
通过分布式条件类型动态生成参数列表,让value在对应类型非undefined时强制变为必填项:
interface MY_TYPES { 'xyz': string; 'abc': number; 'baz': undefined; } // 条件类型:根据键的对应类型判断参数是否必填 type RequiredIfNotUndefined<T extends keyof MY_TYPES> = MY_TYPES[T] extends undefined ? [key: T, value?: undefined] : [key: T, value: MY_TYPES[T]]; function testIt<T extends keyof MY_TYPES>(...args: RequiredIfNotUndefined<T>) { const [key, value] = args; console.log(key); // 改用value !== undefined判断,避免undefined被if(value)过滤 if (value !== undefined) { console.log(value); } }
测试验证:
testIt('xyz', 123);→ 报错(value应为string),符合预期testIt('xyz');→ 报错(value必填),符合预期testIt('xyz', 'str');→ 正常,符合预期testIt('baz');→ 正常,符合预期testIt('baz', 3);→ 报错(value必须为undefined),符合预期
方案二:使用函数重载
如果MY_TYPES的键数量较少,也可以用函数重载明确区分两种场景:
interface MY_TYPES { 'xyz': string; 'abc': number; 'baz': undefined; } // 重载1:对应类型非undefined的键,value必填 function testIt<T extends 'xyz' | 'abc'>(key: T, value: MY_TYPES[T]): void; // 重载2:对应类型为undefined的键,value可选 function testIt(key: 'baz', value?: undefined): void; // 函数实现 function testIt<T extends keyof MY_TYPES>(key: T, value?: MY_TYPES[T]) { console.log(key); if (value !== undefined) { console.log(value); } }
方案对比
- 条件类型方案:扩展性强,当
MY_TYPES新增键时无需修改函数定义,自动适配类型规则 - 函数重载方案:逻辑直观,但需要手动维护重载签名,适合键数量固定且较少的场景
内容的提问来源于stack exchange,提问作者coure2011
相关产品推荐
相关产品推荐

