Cast Object To Interface In TypeScript
Answer :
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(); }
Edit
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);
Here's another way to force a type-cast even between incompatible types and interfaces where TS compiler normally complains:
export function forceCast<T>(input: any): T { // ... do runtime checks here // @ts-ignore <-- forces TS compiler to compile this as-is return input; }
Then you can use it to force cast objects to a certain type:
import { forceCast } from './forceCast'; const randomObject: any = {}; const typedObject = forceCast<IToDoDto>(randomObject);
Note that I left out the part you are supposed to do runtime checks before casting for the sake of reducing complexity. What I do in my project is compiling all my .d.ts
interface files into JSON schemas and using ajv
to validate in runtime.
If it helps anyone, I was having an issue where I wanted to treat an object as another type with a similar interface. I attempted the following:
Didn't pass linting
const x = new Obj(a as b);
The linter was complaining that a
was missing properties that existed on b
. In other words, a
had some properties and methods of b
, but not all. To work around this, I followed VS Code's suggestion:
Passed linting and testing
const x = new Obj(a as unknown as b);
Note that if your code attempts to call one of the properties that exists on type b
that is not implemented on type a
, you should realize a runtime fault.
Comments
Post a Comment