Typescript cast object to interface

How to Convert JSON Object to Interface or class in typescript?

This post talks about different ways of converting json to interface in typescript.

During development, data comes from the REST API in the format of JSON format, So you need to write a code to convert the JSON to interface or class in typescript.

We are going to learn various ways of converting JSON objects to Interface/class. In my previous article, Learned how to declared and implement typescript interfaces.

This conversion is required to know as Front applications coded in typescript and calls REST API that interns call backend services, and returns the response in JSON format.

This JSON object needs to transfer to the interface/class to bind this data to UI.

Interfaces have no implementation but it has some rules, where classes or objects that implement this interface should follow it.

How to Convert json to Object or interface in typescript?

To convert JSON to the interface, the developer does not need to do anything. simply write code that follows some rules to allow the typescript compiler to do the conversion. First, the Interface is defined with properties the same as JSON fields.

  • Interface fields are a subset of the JSON object
  • Interface fields names and types should match with object data
Читайте также:  Java jep что такое

Implicit interface conversion

The developer will not write any code to do the conversion. just follow the guidelines above and the Typescript compiler will do it automatically

Here is an example using the Implicit conversion approach

The function returns Employee data.

function getEmployees(): Array  return [  id: 1, name: "john", salary: 50000 >,  id: 2, name: "Kiran", salary: 40000 >, ]; >
  • The interface should be created like the below using the interface keyword.
  • Declared interface with three properties, It is not compulsory to declare all properties.
  • You can declare two fields also as per your requirement, but properties names should match with the name of JSON object keys
  • Each JSON object represents an Employee Object. if the JSON object is a list of arrays, Then in your app you should map it to an Array of employees or Employee []

Here is an interface declared in Employee.ts .

interface Employee  id: number; name: string; salary: number; >

Typescript Explicit Interface conversion

In this, The developer will write code to convert to the interface.

It is useful when customizing or processing data before converting it to interfaces or classes.

Using first-class functions — the array’s method map() , iterates through the JSON object array and maps the elements to the interface , as shown in the code below.

const emps = [  'id': 1, 'name': 'john', 'salary': 50000 >, 'id': 2,'name': 'Kiran','salary': 40000> ]; const empsClass: Employee = emps.map(obj =>  id: obj.Id, name: obj.Name >); interface Employee  id: number, name: string, salary: number >

How to map a Nested JSON object to interface in typescript?

  • Each employee has an address with one-to-one mapping.
  • Created two interfaces one for employee and another for address
  • declared mapping address in employee interface using like normal data type declaration.’
  • The same implicit interface mapping rules apply here to declare the address interface.
const emps = [  'id': 1, 'name': 'john', 'salary': 50000, "address":  "colony": "John Road", "state": "NewYork", "country":"USA" >>, 'id': 2,'name': 'Kiran','salary': 40000 "address":  "colony": "Stree 12", "state": "NewYork", "country":"USA" >> ]; interface Employee  id: number, name: string, salary: number, address:Address > interface Address  colony: string, state: string, country:string, >

Custom JSON objects, such as recursive JSON types or tree model data, are used in this approach. Each parent contains children.

We have seen all the above examples with interfaces. You can also do the map JSON to classes.

Summary

To summarize, Learned multiple ways to convert JSON to object or interface were discussed. You can select one approach based on your needs.

Источник

Cast object to interface in TypeScript

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 = 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); 

Solution 2

Here’s another way to force a type-cast even between incompatible types and interfaces where TS compiler normally complains:

export function forceCast(input: any): T < // . do runtime checks here // @ts-ignore

Then you can use it to force cast objects to a certain type:

import < forceCast >from './forceCast'; const randomObject: any = <>; const typedObject = forceCast(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.

Solution 3

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

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.

Elias Garcia

Elias Garcia

Hi! I'm a 25 years old software engineer based in A Coruña, Spain. You can see all of my works in my Github page!

Comments

Elias Garcia

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; >; 
@Post() addToDo(@Response() res, @Request() req) < const toDo: IToDoDto = req.body; //
public addToDo(toDo: IToDoDto): void

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?

Please define "it's not working". Be precise. Is there an error? Which one? At compile-time? At runtime? What happens?

Источник

Cast object to interface in TypeScript

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 = req.body;// orconst 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);

Источник

[object] Cast object to interface in TypeScript

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.

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 = req.body; //

And finally, the service method that's being called:

public addToDo(toDo: IToDoDto): void

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?

The answer is

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 = 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(input: any): T < // . do runtime checks here // @ts-ignore

Then you can use it to force cast objects to a certain type:

import < forceCast >from './forceCast'; const randomObject: any = <>; const typedObject = forceCast(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

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.

Источник

Оцените статью