如何标记辅助函数已校验event.body非空以消除TS(18047)错误?
让TypeScript识别辅助函数已完成非空校验的解决方案
我有一个可复用的辅助函数:
const eventCommonChecks = (event: APIGatewayEvent): any => { if(!event.body) { return { "status": 400, "body": "Missing body" } } // 其他若干校验逻辑 }
调用这个辅助函数时,如果event.body为空,调用方会直接返回错误响应,此时event.body必然非空,但TypeScript编译器仍报错:'event.body' is possibly 'null'.ts(18047),必须用可选链调用才能通过检查。想知道怎么修饰这个辅助函数,让TypeScript识别它已经完成了event.body的非空校验。
调用方函数示例:
const someLambda = (event: APIGatewayEvent): any => { const commonEventCheckResponse = eventCommonChecks(event); if (commonEventCheckResponse) { return commonEventCheckResponse; } // 报错:'event.body' is possibly 'null'.ts(18047) if (!event.body.someFieldInBody) { return { "status": 400, "body": "Missing someFieldInBody" } } }
要解决这个问题,核心是让TypeScript编译器理解:经过eventCommonChecks校验后,event.body不再是null或undefined。可以用类型谓词或断言函数两种方式实现,具体方案如下:
方法一:使用类型谓词(推荐)
修改辅助函数的返回类型,通过类型谓词标记校验通过后event的类型,让TypeScript自动推断event.body非空:
// 定义校验后的类型,确保body非空 type ValidatedAPIGatewayEvent = APIGatewayEvent & { body: NonNullable<APIGatewayEvent['body']> }; function eventCommonChecks(event: APIGatewayEvent): event is ValidatedAPIGatewayEvent | { status: number; body: string } { if (!event.body) { return { "status": 400, "body": "Missing body" } as const; } // 其他校验逻辑,不通过时返回错误对象 // ... // 所有校验通过,返回true,此时TypeScript会认定event是ValidatedAPIGatewayEvent类型 return true; }
调用方只需调整判断逻辑,区分返回值是布尔值(校验通过)还是错误对象:
const someLambda = (event: APIGatewayEvent): any => { const checkResult = eventCommonChecks(event); if (typeof checkResult !== 'boolean') { return checkResult; } // 这里TypeScript自动识别event.body非空,不会再报错 if (!event.body.someFieldInBody) { return { "status": 400, "body": "Missing someFieldInBody" }; } // 后续业务逻辑... };
方法二:使用断言函数
如果希望辅助函数在校验失败时直接抛出错误(而非返回错误对象),可以用断言函数强制TypeScript认定校验通过后event.body非空:
function eventCommonChecks(event: APIGatewayEvent): asserts event is APIGatewayEvent & { body: NonNullable<APIGatewayEvent['body']> } { if (!event.body) { throw new Error(JSON.stringify({ status: 400, body: "Missing body" })); } // 其他校验逻辑,失败时抛出错误 // ... }
调用方需要捕获错误并返回响应:
const someLambda = (event: APIGatewayEvent): any => { try { eventCommonChecks(event); } catch (err) { return JSON.parse((err as Error).message); } // 此处event.body已被断言为非空,编译器不再报错 if (!event.body.someFieldInBody) { return { "status": 400, "body": "Missing someFieldInBody" }; } // 后续业务逻辑... };
核心原理说明
- 类型谓词:通过
event is ValidatedAPIGatewayEvent告诉编译器,当函数返回true时,传入的event参数符合指定的校验后类型;返回错误对象则表示校验失败。 - 断言函数:通过
asserts event is ...声明,只有当函数正常执行完毕(未抛出错误)时,event才符合断言的类型,强制编译器认可后续代码中event.body非空。
内容的提问来源于stack exchange,提问作者scott.korin
相关产品推荐
相关产品推荐

