TypeScript泛型解析为交叉类型问题及body.name访问方案咨询
TypeScript交叉类型
SignRequest & {}成因与 idiomatic 访问方案 一、为什么body的类型是SignRequest & {}?
你在SignUpController的handle方法里,把SignRequest声明成了泛型参数,这会遮蔽外部定义的同名SignRequest接口。TypeScript会将这个泛型参数视为一个无任何约束的未知类型,结合HttpRequest<T>中body?: T的定义:
- 初始时
httpRequest.body的类型是T | undefined | null - 当你通过
if判断排除null和undefined后,TypeScript会做类型收窄,将其变为T & {}(因为{}类型可以排除null和undefined)
此时的SignRequest是无约束泛型,自然没有name属性,所以访问body.name会报错。
二、符合TypeScript风格的body.name访问方式
方案1:移除不必要的泛型(推荐)
SignUpController是专门处理注册请求的控制器,不需要泛型,直接指定请求和响应的类型为外部的SignRequest接口即可:
export class SignUpController implements Controller { handle(httpRequest: HttpRequest<SignRequest>): HttpResponse<SignRequest> { if (httpRequest.body === null || httpRequest.body === undefined) { throw new Error("Bad Request") } const body = httpRequest.body; // 类型为SignRequest console.log(body.name); // 正常访问,无类型错误 throw new Error("Not implemented exception"); } }
方案2:给泛型添加约束(适用于通用控制器场景)
如果需要控制器支持多种请求类型,给泛型参数添加继承约束,确保它包含SignRequest的属性:
export class SignUpController implements Controller { handle<T extends SignRequest>(httpRequest: HttpRequest<T>): HttpResponse<T> { if (httpRequest.body === null || httpRequest.body === undefined) { throw new Error("Bad Request") } const body = httpRequest.body; // 类型为T,继承自SignRequest console.log(body.name); // 类型检查通过 throw new Error("Not implemented exception"); } }
内容的提问来源于stack exchange,提问作者Cássio
相关产品推荐
相关产品推荐

