如何实现继承枚举的泛型Type Guard,自动推导关联数组类型?
泛型枚举的类型守卫实现方案
要让泛型函数里的fruitSalad跟着类型守卫自动缩小类型,你需要实现**能约束泛型参数T**的类型守卫,而不是仅缩小参数本身的类型。
针对单个枚举成员的解决方案
直接修改类型守卫的类型谓词,基于泛型T提取目标枚举成员类型:
enum Fruit { Apple = "apple", Banana = "banana", } // 泛型类型守卫:从T中提取属于Fruit.Apple的类型 function isApple<T extends Fruit>(fruit: T): fruit is Extract<T, Fruit.Apple> { return fruit === Fruit.Apple; } function exemple<T extends Fruit>(fruit: T, fruitSalad: T[]) { if (isApple(fruit)) { // 此时fruitSalad自动推导为Fruit.Apple[]类型 console.log(fruitSalad); // 类型验证:无编译错误 const appleSalad: Fruit.Apple[] = fruitSalad; } }
为什么这个方案可行?
Extract<T, Fruit.Apple>会从泛型T中筛选出与Fruit.Apple兼容的类型。当isApple返回true时,TypeScript会自动推断T的实际类型就是Fruit.Apple,因此fruitSalad的类型也会从T[]缩小为Fruit.Apple[]。- 你之前的写法报错是因为直接断言
fruit is Fruit.Apple,但T可能是Fruit的任意子类型(比如Fruit.Banana),此时Fruit.Apple无法赋值给T,触发类型不兼容错误。
通用枚举类型守卫(适用于所有枚举成员)
如果需要为多个枚举成员快速生成守卫,可以写一个通用工具函数:
// 通用枚举成员类型守卫生成器 function createEnumGuard<T extends Record<string, string | number>>(enumObj: T) { return <U extends T[keyof T]>(member: U) => { return (value: T[keyof T]): value is U => { return value === member; }; }; } // 生成针对Fruit枚举的守卫 const fruitGuard = createEnumGuard(Fruit); const isApple = fruitGuard(Fruit.Apple); const isBanana = fruitGuard(Fruit.Banana); function exemple<T extends Fruit>(fruit: T, fruitSalad: T[]) { if (isBanana(fruit)) { // fruitSalad自动推导为Fruit.Banana[] console.log(fruitSalad); } }
内容的提问来源于stack exchange,提问作者Ppdpjuju
相关产品推荐
相关产品推荐

