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

Popular posts from this blog

Are Regular VACUUM ANALYZE Still Recommended Under 9.1?

Can Feynman Diagrams Be Used To Represent Any Perturbation Theory?