使用方法将来自后端的 JSON 个对象键入为正确的打字稿 类

Typing JSON objects coming from the backend as proper typescript classes with methods

我正在尝试将从后端返回的 json 映射到 angular 端的正确打字稿 classes。

这是我的后端代码:

findMessagesWithOtherUserAccount(otherId:Number):Observable<Message[]> {
    return this.http.get('/api/message/find-messages-with-other-useraccount/' + otherId)
        .map(this.extractMessages);
}

private extractMessages(res:Response) {
    let body = res.json();
    return body || {};
}

注意 MessageObservable。这里 Message 是我需要的类型,因为我在 class 中添加了如下业务逻辑:

import {UserAccount} from "../useraccount/useraccount.model";

export class Message {

    constructor(id:number,
                sender:UserAccount,
                recipient:UserAccount,
                sendDate:Date,
                messageRead:boolean,
                text:string) {
        this.id = id;
        this.sender = sender;
        this.recipient = recipient;
        this.sendDate = sendDate;
        this.messageRead = messageRead;
        this.text = text;
    }

    id:number;
    sender:UserAccount;
    recipient:UserAccount;
    sendDate:Date;
    messageRead:boolean;
    text:string;

    getCounterparty(user:UserAccount):UserAccount {
        if (!this.sender) return null;
        return (user.id !== this.sender.id) ? this.sender : this.recipient;
    }

    isSender(user:UserAccount):boolean {
        return user.id === this.sender.id;
    }

    isRecipient(user:UserAccount):boolean {
        return user.id === this.recipient.id;
    }

    isNew(user:UserAccount):boolean {
        return !this.messageRead && this.isRecipient(user);
    }
}

我尝试从组件中引用 isRecipient 方法:

   getSenderFirstName(message:Message):string {
        if (message.isRecipient(this.currentUserAccount)) {
            return this.otherUserAccount.firstName;
        }
        return 'Moi';//FIXME: i18n/translate
    }

但是,我得到这个错误:

browser_adapter.js:81 TypeError: message.isRecipient is not a function
    at MessageConversationComponent.getSenderFirstName (message-conversation.component.js:50)

表示消息未键入(普通 js 对象除外)...

这是完整的组件:

export class MessageConversationComponent implements OnInit {

    messagesWithOtherUserAccount:Message[];
    currentUserAccount:UserAccount;
    otherUserAccount:UserAccount;

    constructor(private messageService:MessageService,
                private userAccountService:UserAccountService,
                private routeSegment:RouteSegment) {
    }

    ngOnInit() {
        this.messageService.findMessagesWithOtherUserAccount(2)
            .subscribe(param=>this.messagesWithOtherUserAccount = param);
        this.userAccountService.retrieveOtherUserAccount(2)
            .subscribe(param=> this.otherUserAccount = param); 
   this.userAccountService.currentUserAccount$.subscribe(param=>this.currentUserAccount = param);
    }

    getSenderFirstName(message:Message):string {
        if (message.isRecipient(this.currentUserAccount)) {
            return this.otherUserAccount.firstName;
        }
        return 'Moi';//FIXME: i18n/translate
    }
}

和模板:

            <div *ngFor="let message of messagesWithOtherUserAccount" class="media col-xs-12">
                <div class="media-body Lui" ng-class="getMessageClasses(message)">
                    <div class="media-heading">
                        {{getSenderFirstName(message)}} <small><span am-time-ago="message.sendDate"></span></small>
                    </div>
                    <p class="message-text">{{message.text}}</p>
                </div>
            </div>

您不能只将 JSON 转换为 class 实例。如果你真的需要一个 class 的方法,你需要用 new SomeClass() 创建它,比如:

private extractMessages(res:Response) {
    let body = res.json();

    if(body) {
      return new Message(
        body.id,
        new UserAccount(body.sender),
        new UserAccount(body.recipient),
        new Date(body.sendDate),
        body.messageRead,
        body.text);
    } else {
      return new Message(
    }
}

如果您只想对属性进行类型化访问,您可以使用接口而不是 class 并强制转换为该接口以获取自动完成和静态类型检查。