網站搜尋

javascript - Typescript:如何將物件屬性標記為不可列舉?


我正在使用名義型別/品牌來表示通過 React 的 useMemo 的值。

type Memoed<T> = T extends Primitive ? T
  : T extends { __MEMOED: true } ? T
  : T & { __MEMOED: true };

declare function useMemo<T extends any>(
  callback: () => T,
  deps: ReadonlyArray<Primitive | Memoed<object>>,
): Memoed<T>;

這大部分時間運作良好。然而,當我使用 Object.keys、Object.values 或者在展開物件時,會造成問題。例如,如果我展開一個被記憶化的物件以創建一個新物件,新的物件並沒有被記憶化。然而,它仍然會有 __IS_USE_MEMO 屬性,因此 Typescript 會允許它作為 useMemo 的參數。例如:

const objA = useMemo(() => ({ a: 1 }), []);
const objB = { ...objA };
const objC = useMemo(() => objB, [objB]); // Should be error

TS 遊樂場

如果我可以將 __MEMOED 設為不可列舉,那麼這個問題應該就會消失。這可能嗎?

答案#1

看起來唯一的方法是定義一個類,將你的「memoed」標記作為方法(技術上不必是方法,但用其他方式擴展原型會更複雜)。

這似乎真的有效(而不是你對 __MEMOED 的定義):

declare class __MEMOED {
  memoed(): true
}

type Memoed<T> = T extends Primitive ? T
  : T extends __MEMOED ? T
  : T & __MEMOED

雖然……如果你備忘錄任何不是基本對象的東西,情況會變得非常奇怪,到了那時你真的需要擴展基類。