I'm trying to make a cast in my code from the body of a request in express (using body-parser middleware) to an interface, but it's not enforcing type safety.
This is my interface:
export interface IToDoDto {
description: string;
status: boolean;
};
This is the code where I'm trying to do the cast:
@Post()
addToDo(@Response() res, @Request() req) {
const toDo: IToDoDto = <IToDoDto> req.body; // <<< cast here
this.toDoService.addToDo(toDo);
return res.status(HttpStatus.CREATED).end();
}
And finally, the service method that's being called:
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. I would expect, if the cast from response body to interface is not possible, that an exception would be thrown at runtime like Java or C#.
I have read that in TypeScript casting doesn't exist, only Type Assertion, so it will only tell the compiler that an object is of type x
, so... Am I wrong? What's the right way to enforce and ensure type safety?
If we want to cast the object to string data types by using toString() method we can change the object type to a string data type. We can also cast the object type to jsonby using json. parse() method we can get only the plain objects and it not used on the class object.
JavaScript doesn't have a concept of type casting because variables have dynamic types. However, every variable in TypeScript has a type. Type castings allow you to convert a variable from one type to another. In TypeScript, you can use the as keyword or <> operator for type castings.
To create an object based on an interface, declare the object's type to be the interface, e.g. const obj1: Employee = {} . The object has to conform to the property names and the type of the values in the interface, otherwise the type checker throws an error.
There's no casting in javascript, so you cannot throw if "casting fails".
Typescript supports casting but that's only for compilation time, and you can do it like this:
const toDo = <IToDoDto> req.body;
// or
const toDo = req.body as IToDoDto;
You can check at runtime if the value is valid and if not throw an error, i.e.:
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();
}
As @huyz pointed out, there's no need for the type assertion because isToDoDto
is a type guard, so this should be enough:
if (!isToDoDto(req.body)) {
throw new Error("invalid request");
}
this.toDoService.addToDo(req.body);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With