網站搜尋

javascript - 在 Typescript 類中透過 Object.assign 擴展 `this`


我有一個物件 remote,它本身不是一個類別實例。由於 Angular 2-5 的特性,我需要把這個物件包裝在一個服務中,以便我可以將它注入到組件中。該物件有一個介面聲明為 'Remote'。

我該如何讓以下內容運作?

import { Injectable } from '@angular/core';
import { remote, Remote } from 'electron';

@Injectable()
export class RemoteService implements Remote {
    constructor() {
        Object.assign(this, remote);
    }
}

也就是,我如何建立一個服務類別 RemoteService,其實例看起來像 Remote,而不需要手動包裝所有 remote 的成員?我不能使用繼承,因為 remote 本身不是類別的實例,只是一個物件。

在上面的例子中,Typescript 編譯器會抱怨 RemoteService 錯誤地實作了 Remote(這很自然)。有沒有辦法強制編譯器將 RemoteService 理解為實作了 Remote?

答案#1

TypeScript 類別應該與介面進行增強。這會產生合併聲明,確認 Remote 方法已被實作:

import { remote, Remote } from 'electron';

export interface RemoteService extends Remote {}

@Injectable()
export class RemoteService implements Remote {
    constructor() {
        Object.assign(this, remote);
    }
}

Object.assign 只有在屬性是常數,且方法是自身且可列舉時才能正常工作。

為了更有效的繼承,可以創建基類以提供原型鏈:

import { remote, Remote } from 'electron';

export interface BaseRemote extends Remote {}
export class BaseRemote implements Remote {}
Object.setPrototypeOf(BaseRemote.prototype, remote);
// or
/*
export const BaseRemote = function BaseRemote() {} as Function as { new(): Remote };
BaseRemote.prototype = remote;
*/

@Injectable()
export class RemoteService extends BaseRemote {
    /* custom methods */
}

如果一個類擴展了一個對 this 上下文有限制的特殊對象(參見帶有原生 sessionStorage 對象的示例),或者對象的方法已經被綁定,無論如何都應該為原始方法提供包裝方法。如果包裝方法是通過程序方式創建的(例如通過 for..in 遍歷屬性等)而不是通過 class 語法創建,則還應額外使用合併聲明以獲得正確的類型。