TypeScript中如何传播类型守卫?复用逻辑时传递类型谓词
复用类型守卫逻辑并传播类型谓词
要实现调用expectToken后自动窄化token的类型,你可以通过泛型+类型守卫函数的类型约束来提取并传播guardfn的类型谓词,具体改造如下:
改造后的代码
type TokenType = `NumericLiteral`; // 可扩展为更大的联合类型 interface Token { type: TokenType; raw: string; value?: unknown; } interface NumericLiteral extends Token { type: `NumericLiteral`; value: number; } function isNumericLiteral(token: Token): token is NumericLiteral { return token.type === `NumericLiteral`; } // 泛型T表示守卫后得到的具体Token子类型 function expectToken<T extends Token>( token: Token | undefined, type: TokenType, guardfn: (token: Token) => token is T ): asserts token is T { // 使用asserts语法声明参数的类型断言 if (!token || !guardfn(token)) { const received = token ? token.type : `nothing`; throw new Error(`Expected ${type} but got ${received}`); } } const token = { type: `NumericLiteral`, value: 123 } as Token; expectToken(token, `NumericLiteral`, isNumericLiteral); // 此时token已被窄化为NumericLiteral类型,可以直接访问value属性 console.log(token.value.toFixed(2)); // 类型检查通过
关键改动说明
- 泛型T约束:用
T extends Token指定守卫函数最终要断言的目标子类型,让TypeScript能关联guardfn的类型谓词和输入参数的类型。 - 类型守卫函数参数:将
guardfn的类型从普通布尔返回值改为(token: Token) => token is T,明确告知TypeScript这个函数是用于将Token断言为T的类型守卫。 - asserts类型断言:函数返回值使用
asserts token is T语法,这是TypeScript的断言函数特性,表明如果函数正常执行(不抛出错误),则输入的token必然是T类型,从而实现调用后的自动类型窄化。
这种方式不仅能复用通用的校验逻辑,还能完美保留类型守卫的类型推导能力,适用于所有Token子类型的守卫函数复用。
内容的提问来源于stack exchange,提问作者Adam B.
相关产品推荐
相关产品推荐

