如何实现函数双参数类型映射并保证paramMapType的类型安全?
问题描述
我定义了如下枚举:
export enum testEnum { key1 = "val1", key2 = "val2" }
有一个函数,第一个参数为testEnum类型,第二个参数的类型由第一个参数传入的枚举值决定,实现如下:
function testFunc<T extends `${testEnum}`>( param1: T, param2: paramMapType[T], ): Promise<void> { /* ... */ }
同时定义了用于类型映射的类型:
type paramMapType = { val1: string; val2: boolean };
现在的问题是paramMapType缺乏类型安全,无法确保其键必须是testEnum的枚举值。我尝试以下写法:
type paramMapType = { [key in `${testEnum}`]: any val1: string; val2: boolean };
但报错:A mapped type may not declare properties or methods.。用条件类型又太冗长且无法保证类型安全,请问该如何实现?
解决方案
方案一:映射类型+条件类型直接定义
直接通过映射类型遍历testEnum的所有枚举值,搭配条件类型为每个值指定对应参数类型,能严格保证键与枚举值一一对应,不会遗漏或多余:
export enum testEnum { key1 = "val1", key2 = "val2" } type paramMapType = { [K in `${testEnum}`]: K extends testEnum.key1 ? string : K extends testEnum.key2 ? boolean : never; }; function testFunc<T extends `${testEnum}`>( param1: T, param2: paramMapType[T], ): Promise<void> { // 函数实现 return Promise.resolve(); }
方案二:用satisfies关键字约束(TypeScript 4.9+)
如果希望先手动定义具体的类型映射,再约束其键必须匹配枚举值,可以使用satisfies运算符(TS 4.9及以上版本支持),既保留具体类型信息,又保证类型安全:
export enum testEnum { key1 = "val1", key2 = "val2" } // 定义约束:键必须是testEnum的枚举值 type RequiredParamMap = Record<`${testEnum}`, unknown>; // 手动定义映射,用satisfies确保符合约束 const paramMapDef = { val1: "" as string, val2: false as boolean } satisfies RequiredParamMap; // 从约束后的对象提取类型 type paramMapType = typeof paramMapDef; function testFunc<T extends `${testEnum}`>( param1: T, param2: paramMapType[T], ): Promise<void> { return Promise.resolve(); }
原写法报错原因
你之前尝试的混合写法之所以报错,是因为映射类型是批量生成属性的语法,不能与手动声明的属性共存,TypeScript不允许这种混合定义方式。
内容的提问来源于stack exchange,提问作者Tyrion Vu Van Phong
相关产品推荐
相关产品推荐

