TypeScript:如何判断构造函数联合参数的真实非原始类型?
问题
现有以下TypeScript代码:
abstract class Base { protected constructor(method: EnumMethod) { ... } } class Leaf { constructor(method: EnumMethod) { super(method); } } enum EnumMethod { CARD = 'card', APPLEPAY = 'applePay', GOOGLEPAY = 'googlePay', }
为让Leaf类兼容原有直接传入EnumMethod的代码,同时支持更多配置项,定义了如下接口:
interface Params { method: EnumMethod; foo: string; bar: number; }
希望将Leaf类的构造函数参数改为EnumMethod | Params类型,并通过类型判断区分参数类型以调用父类构造函数,示例代码如下:
class Leaf { constructor(params: EnumMethod | Params) { super(params is EnumMethod ? params : params.method); } }
请问如何在TypeScript中实现上述is操作符的类型判断逻辑?
解决方案
在TypeScript中,要实现这种自定义类型判断,需要编写自定义类型守卫函数,通过is关键字明确类型判断后的类型,具体实现步骤如下:
1. 编写类型守卫函数
定义一个函数,用来判断传入值是否属于EnumMethod类型:
function isEnumMethod(value: unknown): value is EnumMethod { // 先判断值是字符串类型,再检查是否存在于EnumMethod的枚举值集合中 return typeof value === 'string' && Object.values(EnumMethod).includes(value as EnumMethod); }
当这个函数返回true时,TypeScript编译器会自动将参数value的类型收窄为EnumMethod。
2. 修改Leaf类的构造函数
在Leaf类的构造函数中,使用上述类型守卫函数完成类型判断:
class Leaf extends Base { constructor(params: EnumMethod | Params) { super(isEnumMethod(params) ? params : params.method); } }
这样既兼容了原有直接传入EnumMethod的调用方式,也支持传入Params对象的新用法。
补充说明
- 类型守卫函数的核心是通过运行时的判断逻辑,给TypeScript编译器提供类型收窄的依据,实现编译时的类型安全。
- 这里的判断逻辑利用了
EnumMethod的枚举值均为字符串的特性,先做基础类型校验,再校验是否属于枚举有效值。
内容的提问来源于stack exchange,提问作者Romulus Urakagi Ts'ai
相关产品推荐
相关产品推荐

