網站搜尋

typescript - 如何將類別導出為唯讀,但允許內部修改?


由於我的類別有非同步初始化過程。我必須定義一個只讀公共屬性,但在內部修改它,比如

declare function asyncAppMap(target: string): Promise<Window>

class FrameInternal {
  public readonly content: Window | null = null
  constructor(target: string) {
    asyncAppMap(target).then(app => {
      // Not possible currently.
      // this.content = app
    })
  }
}

我正在尋找一些可重複使用的工具,例如:

class FrameInternal{}
// Then all members of Frame becomes readonly
export const Frame: ReadonlyClass<FrameInternal> = FrameInternal

答案#1

根據你的具體需求,你可以使用類似這樣的東西:

type ReadonlyClass<T extends new (...args: any) => any> =
    T extends new (...args: infer A) => infer R ?
    new (...args: A) => { readonly [K in keyof R]: R[K] } : never;

類型 ReadonlyClass 將一個建構子類型轉換為新的建構子類型,該類型生成的實例類型的所有屬性都被標記為 readonly。

當你導出一個類別建構函數時,你可能也想導出一個同名的類型,對應於實例類型。當你使用 class Foo {} 表示法時,這會自動發生(Foo 既被引入為類別建構函數的名稱,也被引入為類別實例類型的名稱):

export const Frame: ReadonlyClass<typeof FrameInternal> = FrameInternal;
export type Frame = InstanceType<typeof Frame>;

當你檢查它時,看起來像這樣:

/*
const Frame: new (target: string) => {
    readonly content: Window | null;
}
type Frame = {
    readonly content: Window | null;
}
*/

至少在你上面展示的範例情況下,這應該可行:

const f = new Frame("z");
f.content = null; // error, can't assign to read only

function acceptFrame(f: Frame) {
    f.content = null; // error here too    
}

好的,希望那有幫助;祝你好運!

程式碼連結