2016-09-10 3 views
1

Я использую TypeScript для создания приложения, и я делаю вызовы API для извлечения объектов. Например, у меня есть машинопись User объекта, как это:Тип машинописного объекта от JSON

export class User { 
    id : number; 
    name : string; 
    email : string; 
} 

И мой API возвращает

{ 
    "id" : 3, 
    "name" : "Jonn", 
    "email" : "[email protected]" 
} 

Я хочу, чтобы преобразовать этот JSON в User. Я читал в других постов, я могу это сделать:

let user : User = <User> myJson; 

Это, кажется, работает. Я могу получить доступ к свойствам пользователя, например user.name, но моя проблема в том, что если класс User реализует какой-либо метод, свойства недоступны. Например, если внутри User класса у меня есть это:

getUppercaseName() : string { 
    return this.name.toUppercase(); 
} 

Это происходит: user.name возвращается John но user.getUppercaseName() возвращает undefined

Что происходит? Как решить эту проблему

ответ

2

Что вы делаете это лечение классы как интерфейсы, так как это будет работать точно так же:

export interface User { 
    id : number; 
    name : string; 
    email : string; 
} 

Причина, по которой компилятор не жалуется на вас, используя классы таким образом is because:

Одним из основных принципов TypeScript является то, что проверка типов фокусируется на формах, которые имеют значения. Это иногда называют «утиной типизацией» или «структурными подтипами»

(read more about duck typing)

Или с примером:

class User { 
    id: number; 
    name: string; 
    email: string; 

    constructor(id: number, name: string, email: string) { 
     this.id = id; 
     this.name = name; 
     this.email = email; 
    } 
} 

function logUser(user: User) { 
    console.log(`user id: ${ user.id }, name: ${ user.name }, email: ${ user.email }`); 
} 

logUser({ 
    id: 1, 
    name: "user 1", 
    email: "mailaddress" 
}); 

logUser(new User(2, "user 2", "anotheraddress")); 

В двух вызовах logUser я передавать объекты, которые удовлетворяют интерфейс класса User.

Если вы хотите иметь экземпляр этого класса, а не объекта, удовлетворяющего его, то вы должны сделать что-то вроде:

new User(myJson.id, myJson.name, myJson.email); 

И есть конструктор, как в моем примере, или:

interface IUser { 
    id: number; 
    name: string; 
    email: string; 
} 

class User implements IUser { 
    id: number; 
    name: string; 
    email: string; 

    constructor(data: IUser) { 
     this.id = data.id; 
     this.name = data.name; 
     this.email = data.email; 
    } 
} 

... 
new User(myJson); 
+0

Я думаю, что вопрос заключается в том, как преобразовать данные json в конкретный экземпляр класса. Что-то вроде этого должно работать (при условии, что есть конструктор пользователя), но дает мне ошибку, когда я использую результат в ngIf return this._http.get (this.urll) .map ((res: Response) => res .json()) .map (obj: any => {return new User (obj.number, obj.name, obj.email);}) – rook

+0

@rook Нет необходимости использовать 'map' дважды .. это должно work: 'this._http.get (this.urll) .map ((res: Response) => {let json = res.json(); возвращает нового пользователя (json.id, json.name, json.email); }) '. Какая у вас ошибка? –

+0

Да, это короче, но ошибка одна и та же: не удается найти отличающийся поддерживающий объект «объект объекта» типа «объект». NgFor поддерживает только привязку к Iterables, например массивы. – rook

2

Nitzan в значительной степени объясняет теорию позади этого, так что я просто обеспечить альтернативный подход:

interface UserInfo { 
    id: number; 
    name: string; 
    email: string; 
} 

class User { 
    userInfo: UserInfo; 
    constructor(userInfo: UserInfo) { 
     this.userInfo = userInfo; 
    } 
    getUpperCaseName(): string { 
     return this.userInfo.name.toLocaleUpperCase(); 
    } 
} 

const json = { 
    id: 3, 
    name: "Jonn", 
    email: "[email protected]" 
} 

let user: User = new User(json); 
0

Существует проблема, когда у вашего пользователя 50 или более свойств ...

Добавить конструктор в объект User так, чтобы он расширил ваш объект json.

export class User { 
    constructor(jsonUser: any) 
    { 
     $.extend(this, jsonUser); 
    } 
    id : number; 
    name : string; 
    email : string; 
    getUpperCaseName() {...} 
} 

В вашем АЯКС обратный вызов, создать объект пользователя с вашего JSon объекта:

let receivedUser = new User(jsonUser); 
let userName = receivedUser.getUpperCaseName(); 

Я подробно решение в этой post.

Смежные вопросы