我试图在我的代码中从express中的请求主体(使用主体解析器中间件)转换到接口,但它没有强制执行类型安全.

这是我的界面:

export interface IToDoDto {
  description: string;
  status: boolean;
};

这是我试着做演员的代码:

@Post()
addToDo(@Response() res, @Request() req) {
  const toDo: IToDoDto = <IToDoDto> req.body; // <<< cast here
  this.toDoService.addToDo(toDo);
  return res.status(HttpStatus.CREATED).end();
}

最后,要调用的服务方法:

public addToDo(toDo: IToDoDto): void {
  toDo.id = this.idCounter;
  this.todos.push(toDo);
  this.idCounter++;
}

I can pass whatever arguments, even ones that don't come close to matching the interface definition, and this code will work fine.我预计,如果从响应体到接口的转换不可能,那么会在运行时抛出一个异常,比如Java或C#.

我已经读到在类型脚本中不存在强制转换,只有类型断言,所以它只会告诉编译器一个对象是类型x,所以...我错了吗?实施和确保类型安全的正确方法是什么?

推荐答案

javascript中没有强制转换,所以如果"强制转换失败",就不能进行强制转换

const toDo = <IToDoDto> req.body;
// or
const toDo = req.body as IToDoDto;

您可以在运行时判断该值是否有效,如果无效,则抛出错误,即:

function isToDoDto(obj: any): obj is IToDoDto {
    return typeof obj.description === "string" && typeof obj.status === "boolean";
}

@Post()
addToDo(@Response() res, @Request() req) {
    if (!isToDoDto(req.body)) {
        throw new Error("invalid request");
    }

    const toDo = req.body as IToDoDto;
    this.toDoService.addToDo(toDo);
    return res.status(HttpStatus.CREATED).end();
}

编辑

正如@huyz指出的,不需要类型断言,因为isToDoDto是一个类型保护,所以这就足够了:

if (!isToDoDto(req.body)) {
    throw new Error("invalid request");
}

this.toDoService.addToDo(req.body);

Typescript相关问答推荐

是否有一种方法可以创建仅接受可选值或数组值的映射类型

如何在Jest中嘲笑location.back()方法调用进行Angular 组件测试?

无需刷新即可让现场访客逆变

在TypScript手册中可以视为接口类型是什么意思?

TypeScript实用程序类型—至少需要一个属性的接口,某些指定属性除外

有没有一种方法可以在保持类型的可选状态的同时更改类型?

在NextJS中获得Spotify Oauth,但不工作'

将对象属性转换为InstanceType或原样的强类型方法

为什么TypeScript假设文档对象始终可用?

TypeScrip:强制使用动态密钥

常量类型参数回退类型

在VSCode中显示eslint错误,但在终端中运行eslint命令时不显示?(Vite,React,TypeScript)

类型推断对React.ForwardRef()的引用参数无效

如果判断空值,则基本类型Gaurd不起作用

设置不允许相同类型的多个参数的线性规则

如何使函数参数数组不相交?

类型分布在第一个泛型上,但不分布在第二个泛型上

为什么类方法参数可以比接口参数窄

显式推断对象为只读

在类型{}上找不到带有string类型参数的索引签名 - TypeScript