TypeScript中泛型关联类型在switch语句的类型收窄实现
问题分析与解决方案
你的问题核心是:当参数类型为MyType<keyof MapType>时,TypeScript无法自动关联type和value的类型关系,导致switch语句无法收窄value的类型。这是因为MyType<keyof MapType>等价于MyType<EnumType.Type1> | MyType<EnumType.Type2> | MyType<EnumType.Type3>,但此时泛型参数是整个联合类型,而非单个枚举成员,类型关联信息被抹平了。
不用as断言的话,有两种可行方案:
方案一:将函数改为泛型函数
让函数参数保留泛型约束,TypeScript就能跟踪type和value的关联关系:
enum EnumType { Type1 = "Type 1", Type2 = "Type 2", Type3 = "Type 3", } export type MapType = { [EnumType.Type1]: string[]; [EnumType.Type2]: number[]; [EnumType.Type3]: boolean[]; }; interface MyType<Type extends keyof MapType> { id: string; type: Type; value: MapType[Type]; } // 改为泛型函数 const narrowByType = <T extends keyof MapType>(obj: MyType<T>) => { switch (obj.type) { case EnumType.Type1: const value = obj.value; // 类型自动收窄为string[] break; case EnumType.Type2: const numValue = obj.value; // 类型自动收窄为number[] break; case EnumType.Type3: const boolValue = obj.value; // 类型自动收窄为boolean[] break; } };
方案二:将MyType定义为判别式联合类型
直接写出每个枚举成员对应的类型,让type作为判别式,TypeScript会自动在switch中收窄类型:
enum EnumType { Type1 = "Type 1", Type2 = "Type 2", Type3 = "Type 3", } // 直接定义判别式联合类型 type MyType = | { id: string; type: EnumType.Type1; value: string[] } | { id: string; type: EnumType.Type2; value: number[] } | { id: string; type: EnumType.Type3; value: boolean[] }; const narrowByType = (obj: MyType) => { switch (obj.type) { case EnumType.Type1: const value = obj.value; // 类型自动收窄为string[] break; case EnumType.Type2: const numValue = obj.value; // 类型自动收窄为number[] break; case EnumType.Type3: const boolValue = obj.value; // 类型自动收窄为boolean[] break; } };
两种方案都不需要类型断言,就能实现你预期的类型收窄效果。
内容的提问来源于stack exchange,提问作者lukas23
相关产品推荐
相关产品推荐

