TypeScript 4.0.2中如何将unknown类型收窄为字符串枚举?
在TypeScript 4.0.2中将unknown收窄为字符串枚举的解决方案
你的问题在于,TypeScript 4.0.2无法通过Object.values(Fruit).includes()的调用自动将string类型收窄为Fruit枚举类型——内置的数组includes方法的类型守卫逻辑不支持这种枚举成员的推导,所以即便检查通过,变量类型仍会停留在string。
以下是两种可行的解决方式:
方式一:自定义类型守卫(推荐)
通过自定义类型守卫函数,明确告知TypeScript当检查通过时变量的类型为Fruit,这是类型安全且可复用的方案:
enum Fruit { Apple = "Apple", Banana = "Banana", } function getFruitPrice(x: Fruit) { // 示例实现 return x === Fruit.Apple ? 5 : 3; } // 自定义类型守卫:判断值是否为Fruit枚举成员 function isFruit(value: unknown): value is Fruit { return typeof value === 'string' && Object.values(Fruit).includes(value); } const fruit: unknown = "Apple"; // 示例未知类型值 // 使用类型守卫进行类型收窄 if (!isFruit(fruit)) { throw new Error("Invalid fruit type"); } // 此时fruit的类型已被正确收窄为Fruit const price = getFruitPrice(fruit);
方式二:类型断言(简易方案)
如果只是临时场景,也可以在完成所有检查后手动使用类型断言,但这种方式依赖开发者确保检查逻辑的正确性,不如类型守卫安全:
enum Fruit { Apple = "Apple", Banana = "Banana", } function getFruitPrice(x: Fruit) { // 示例实现 return x === Fruit.Apple ? 5 : 3; } const fruit: unknown = "Banana"; // 示例未知类型值 // 先检查是否为字符串 if (typeof fruit !== 'string') throw new Error(); // 再检查是否属于枚举成员 if (!Object.values(Fruit).includes(fruit)) throw new Error(); // 手动断言为Fruit类型 const price = getFruitPrice(fruit as Fruit);
需要注意的是,在TypeScript 4.0.2中,Object.values(Fruit)返回的类型是string[](字符串枚举的成员值本质是字符串),因此直接传入fruit(已确认是string类型)即可,无需额外的类型断言。
内容的提问来源于stack exchange,提问作者Jam
相关产品推荐
相关产品推荐

