TypeScript中如何判断Settings类型为BasicAuth还是UserToken?
解决TypeScript联合类型的类型判断问题
针对你的需求,要区分Settings联合类型的三种配置形式,TypeScript提供了多种类型收窄的方式,以下是几种实用方案:
1. 利用in操作符+typeof直接判断
这是最简单的实现方式,无需额外定义函数,直接在构造函数中通过属性存在性和类型判断来收窄类型:
// 明确三种配置的子类型 type UserTokenSettings = { userToken: string; }; type StringAuthSettings = { auth: string; }; type ObjectAuthSettings = { auth: { username: string; password: string; }; }; type Settings = UserTokenSettings | StringAuthSettings | ObjectAuthSettings; class MyWebService { constructor(settings: Settings) { // 判断是否为带userToken的配置 if ('userToken' in settings) { // 此时TypeScript自动将settings收窄为UserTokenSettings类型 this.handleUserTokenAuth(settings.userToken); } // 判断是否为字符串类型的auth配置 else if (typeof settings.auth === 'string') { // 此时settings被收窄为StringAuthSettings类型 this.handleStringAuth(settings.auth); } // 剩余情况即为对象类型的auth配置 else { // 此时settings被收窄为ObjectAuthSettings类型 this.handleObjectAuth(settings.auth.username, settings.auth.password); } } private handleUserTokenAuth(token: string) { // 处理userToken认证逻辑 } private handleStringAuth(authStr: string) { // 处理字符串auth认证逻辑 } private handleObjectAuth(username: string, password: string) { // 处理对象auth认证逻辑 } }
2. 自定义类型谓词函数
如果需要在多个地方复用类型判断逻辑,可以编写类型谓词函数,明确告知TypeScript当前值所属的子类型:
type UserTokenSettings = { userToken: string }; type StringAuthSettings = { auth: string }; type ObjectAuthSettings = { auth: { username: string; password: string } }; type Settings = UserTokenSettings | StringAuthSettings | ObjectAuthSettings; // 判断是否为UserTokenSettings类型 function isUserTokenSettings(setting: Settings): setting is UserTokenSettings { return 'userToken' in setting; } // 判断是否为StringAuthSettings类型 function isStringAuthSettings(setting: Settings): setting is StringAuthSettings { return 'auth' in setting && typeof (setting as StringAuthSettings).auth === 'string'; } // 判断是否为ObjectAuthSettings类型 function isObjectAuthSettings(setting: Settings): setting is ObjectAuthSettings { return 'auth' in setting && typeof (setting as ObjectAuthSettings).auth === 'object' && (setting as ObjectAuthSettings).auth !== null; } class MyWebService { constructor(settings: Settings) { if (isUserTokenSettings(settings)) { this.handleUserTokenAuth(settings.userToken); } else if (isStringAuthSettings(settings)) { this.handleStringAuth(settings.auth); } else if (isObjectAuthSettings(settings)) { this.handleObjectAuth(settings.auth.username, settings.auth.password); } } // 省略处理方法... }
3. 添加区分属性(最推荐)
给每个子类型添加一个唯一的标识属性(比如type),通过switch-case判断。这种方式可读性最高,类型收窄最明确,尤其适合复杂的联合类型:
// 每个子类型添加type字段作为区分标识 type UserTokenSettings = { type: 'userToken'; userToken: string; }; type StringAuthSettings = { type: 'stringAuth'; auth: string; }; type ObjectAuthSettings = { type: 'objectAuth'; auth: { username: string; password: string; }; }; type Settings = UserTokenSettings | StringAuthSettings | ObjectAuthSettings; class MyWebService { constructor(settings: Settings) { switch (settings.type) { case 'userToken': this.handleUserTokenAuth(settings.userToken); break; case 'stringAuth': this.handleStringAuth(settings.auth); break; case 'objectAuth': this.handleObjectAuth(settings.auth.username, settings.auth.password); break; // TypeScript会自动检查是否覆盖所有联合类型分支,避免遗漏 } } // 省略处理方法... }
这种方式的优势在于,后续新增配置类型时,只需添加对应的子类型和switch分支,TypeScript会自动提示是否有遗漏,类型安全性更强。
内容的提问来源于stack exchange,提问作者Martial
相关产品推荐
相关产品推荐

