TypeScript联合类型疑问:为何未识别sub在两类中存在?
TypeScript联合类型属性访问错误解决
问题原因
这个错误的核心是TypeScript的联合类型属性访问规则:只有当联合类型的所有成员都包含某个属性时,你才能直接访问该属性。你的Identity联合类型包含了AppSyncIdentityIAM和AppSyncIdentityLambda,这两个类型没有sub属性,所以直接访问ctx.identity.sub会触发类型检查错误——哪怕其中两个成员(AppSyncIdentityCognito和AppSyncIdentityOIDC)拥有sub也不行。
解决方法
方法1:用in操作符做内联类型守卫
在访问sub前先检查属性是否存在,TypeScript会自动缩小类型范围:
export function request(ctx: Context) { if (!ctx.identity) { return; } if (!('sub' in ctx.identity)) { return "Unauthorized"; } // 此时TypeScript已识别ctx.identity为AppSyncIdentityCognito | AppSyncIdentityOIDC return "We got a sub"; }
方法2:自定义可复用的类型守卫函数
如果需要多次判断身份类型,可以写一个复用的类型守卫:
function isIdentityWithSub(identity: Identity): identity is AppSyncIdentityCognito | AppSyncIdentityOIDC { return typeof identity === 'object' && identity !== null && 'sub' in identity; } export function request(ctx: Context) { if (!ctx.identity) { return; } if (!isIdentityWithSub(ctx.identity)) { return "Unauthorized"; } return "We got a sub"; }
方法3:提取含sub的公共类型
先定义一个包含sub的基础类型,让相关身份类型继承它,让类型结构更清晰:
// 定义含sub的公共类型 type IdentityWithSub = { sub: string; issuer: string; claims: any; }; // 让Cognito身份类型继承公共类型 export type AppSyncIdentityCognito = IdentityWithSub & { sourceIp: string[]; username: string; groups: string[] | null; defaultAuthStrategy: string; }; // OIDC身份类型直接复用公共类型 type AppSyncIdentityOIDC = IdentityWithSub; // 后续判断逻辑不变 export function request(ctx: Context) { if (!ctx.identity) { return; } if (!('sub' in ctx.identity)) { return "Unauthorized"; } return "We got a sub"; }
内容的提问来源于stack exchange,提问作者Måns Dahlström
相关产品推荐
相关产品推荐

