14

I'm trying to make a class Post contains post attributes such as "id, title, content ...etc.

I want to initialize the class from a JSON response. I'm using angular-http to get JSON in typescript

in APP.TS:

class AppComponent {

  result: { [key: string]: string; };
  
  map: Map<Object,Object>;
  
  constructor(http: Http) {
    http.get('http://localhost/wptest/wp-json/wp/v2/posts').subscribe(res => {
      
      this.result = <any>res.json();
      this.map = <any>res.json();
      
      console.log(this.result);
      console.log(this.map);     
    });
  }
}

note: I'm still confused about which is the right type for my JSON I read that typescript is not supporting Map yet, however it is working here as result: {[key:string]: string; };

I tried to look up on stackoverflow, I found this question how to cast a json object to a typescript, the answer has nothing to do with typescript.

in another question Can I create a TypeScript type and use that when AJAX returns JSON data?

the answer is talking about creating interfaces in typescript. (which I didn't quite understand it.)

I also found this site for json2ts generates typescript interfaces from JSON, so I tried my json and I got this:

declare module namespace {

    export interface Guid {
        rendered: string;
    }

    export interface Title {
        rendered: string;
    }

    export interface Content {
        rendered: string;
    }

    export interface Excerpt {
        rendered: string;
    }

    export interface Self {
        href: string;
    }

    export interface Collection {
        href: string;
    }

    export interface Author {
        embeddable: boolean;
        href: string;
    }

    export interface Reply {
        embeddable: boolean;
        href: string;
    }

    export interface VersionHistory {
        href: string;
    }

    export interface Links {
        self: Self[];
        collection: Collection[];
        author: Author[];
        replies: Reply[];
    }

    export interface RootObject {
        id: number;
        date: Date;
        guid: Guid;
        modified: Date;
        modified_gmt: Date;
        slug: string;
        type: string;
        link: string;
        title: Title;
        content: Content;
        excerpt: Excerpt;
        author: number;
        featured_image: number;
        comment_status: string;
        ping_status: string;
        sticky: boolean;
        format: string;
        _links: Links;
    }
}

Now I've got a typescript interface for my JSON, but I don't know what to do next!

Q: Is this the right way to parse JSON to a class object in typescript? if yes what is the next step to get the class initialized with the data?

Community
  • 1
  • 1
Murhaf Sousli
  • 12,622
  • 20
  • 119
  • 185

1 Answers1

20

You should definitely use interfaces to describe your DTO (Data Transfer Object). It looks like the json2ts did a good job in describing your JSON structure. Now, because the http service created the object for you, you don't have to create a new one... you only have to cast it to your interface, something like in the following lines:

class AppComponent {
  dataFromServer : RootObject;

  http.get('http://localhost/wptest/wp-json/wp/v2/posts').subscribe(res => {
    this.dataFromServer = <RootObject>res.json();
  });
}

From that point TypeScript will guard you from doing any mistakes when you try to access any data that came from the server. For example:

this.dataFromServer.age = 45; // Error: age doesn't exist in the RootObject interface
this.id = "Hello"; // Error, id was is a number, and you try to put string into it.
this.id = 100; // will be just fine.
omt66
  • 4,765
  • 1
  • 23
  • 21
gilamran
  • 7,090
  • 4
  • 31
  • 50
  • it worked, so there is no need for creating a custom class for the interface? – Murhaf Sousli Nov 20 '15 at 17:56
  • 1
    You are not the creator of this object, do no class. Unless you want to start doing actions (functions) with this object – gilamran Nov 20 '15 at 19:56
  • 1
    But what if I don't know what the JSON will contain? How can I create interfaces for objects that I do not know the contents of? – Kokodoko Jun 12 '16 at 12:19
  • @Kokodoko Did you find an answer to this question? – PCK Sep 06 '17 at 08:37
  • 1
    Remember, TypeScript is for dev time only, and your server response will be given on run-time... meaning that you can "help" yourself by casting the given JSON. Is it not promised that the server will returned what you assume. – gilamran Sep 06 '17 at 14:02
  • 1
    If you really don't know what JSON the server is going to return, you'll just have to type it as `:any` first and then check if properties exist on the json object. After that you can cast it to the corresponding type. Something like `if(obj.actor) mytypedobject = obj`. – Kokodoko Sep 07 '17 at 12:33
  • I would also use `typescript-json-schema` package to generate a json schema for the interface that was defined, and then you first validate the data that came from the server, and then you can cast it safely knowing it is in the right structure. – Max Apr 01 '20 at 15:23