[英]Assign class instance property a value based on its type in Typescript Angular
我不知道這在 Typescript 中是否允許,但我正在一個 Angular 7 項目中工作,我想實例化一個Page
類來填充他從 DB 對象的所有屬性。 這些是我的課程:
export class User {
id: number;
name: string;
created_at: string;
constructor(obj?: any) {
Object.assign(this, obj);
}
getName(): string {
return this.name;
}
}
export class Page {
id: number;
title: string;
author: User;
constructor(obj?: any) {
Object.assign(this, obj);
}
showTitle(): string {
return this.title;
}
}
這是我檢索數據的服務方法的示例:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Page } from '../models/page';
@Injectable()
export class PageService {
constructor(httpClient: HttpClient) {}
getPage(id: number): Observable<Page> {
return this.httpClient
.get<Page>('http://<my-server-ip>:<port>/api/pages')
.pipe(
map((page: Page) => {
console.log('retrieved', page);
return new Page(page);
})
);
}
}
這是我的組件中此函數調用的示例
export class MyCustomComponent implements OnInit {
constructor(pageService: PageService) {}
ngOnInit() {
this.pageService.getPage()
.subscribe((page: Page) => {
console.log(page.showTitle());
});
}
}
此示例有效,但是當我想訪問User
方法時,例如:
console.log(page.author.getName());
我無權訪問它們,因為它不是User
類的實例化。
如果我不將頁面類的新實例作為可觀察對象返回, Page
也會發生同樣的情況,這就是我在檢索數據后使用return new Page(page)
的原因。
問題是我想讓我的構造函數盡可能通用,所以創建一個構造函數來手動分配值(例如: this.author = new User(obj.author);
)不是一個有效的解決方法,因為我想在每個模型中實現它或創建一個GenericModel
然后擴展我的所有模型。
有沒有辦法在實例化類中根據其類型填充具有定義類型的屬性?
這是我到目前為止嘗試過的,但它不起作用:
export class Page {
// ...
constructor(obj?: any) {
Object.keys(obj).forEach((key: string, index: number) => {
if (typeof(obj[key]) === 'object' && obj[key] !== null) {
this[key] = new (this[key].constructor)(obj[key]);
} else {
this[key] = obj[key]
}
});
}
}
ERROR TypeError: Cannot read property 'author' of null
ERROR TypeError: Cannot read property 'constructor' of undefined
我知道在調用構造函數時this
是 null,但我找不到另一種方法來用new
實例填充author
屬性以訪問方法。 此外,如果我得到一個標准/默認對象,如{ ... }
, if
將觸發並且可能也會拋出錯誤,因為它沒有構造函數。
你可以像這樣使用Object.assign
:
getPage(id: number): Observable<Page> {
return this.httpClient
.get<Page>('http://<my-server-ip>:<port>/api/pages')
.pipe(
map((page: Page) => {
console.log('retrieved', page);
return Object.assign(new Page(), page);
})
);
}
此代碼創建一個新的 Page 實例,然后從返回的響應(本例中為page
)復制所有屬性。
然后你不需要修改你的構造函數。
更新
注意:spread 語法只復制屬性,所以我改為使用Object.assign
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.