根据TypeScript Angular中的类型为类实例属性分配一个值

时间:2019-01-25 12:02:24

标签: javascript angular typescript angular7

我不知道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为空,但是我找不到其他方法来用author实例填充new属性来访问方法。另外,如果我得到像{ ... }这样的标准/默认对象,则if将触发并且可能也会引发错误,因为它没有构造函数。

1 个答案:

答案 0 :(得分:0)

您可以像这样使用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)。

然后,您无需修改​​构造函数。

更新

注意:传播语法仅复制属性,因此我改为使用Object.assign