簡體   English   中英

通用 function 獲取具有默認值的可選屬性值

[英]Generic function getting optional property value with default value

有一個 object 類型,如下面的X 請注意,所有屬性都是可選的,它們的類型不同,並且對於某些屬性, null是一個有效值。

type X = {
  a?: number | null;
  b?: string;
  c?: boolean | null;
};

現在,為了方便起見,我想制作一個 function 來獲取X的屬性值之一。 function 可以接受默認值並在屬性缺失時返回它。

我寫的function如下:

function get<K extends keyof X>(k: K, x: X, defaultValue: Required<X>[K]): Required<X>[K] {
  const v = x[k];
  return v !== undefined ? v : defaultValue;
}

因為屬性是可選的,所以我使用Required<X>[K]來獲取有效的屬性類型(不包括undefined )。

我的預期結果是:

// a: number | null = 12345
const a = get('a', {}, 12345);
// b: string = 'bar'
const b = get('b', { b: 'bar' }, '?');
// c: boolean | null = null
const c = get('c', {}, null);

但是我在get function 的返回語句中得到了以下編譯器錯誤。

Type 'Required<X>[K] | (X[K] & ({} | null))' is not assignable to type 'Required<X>[K]'.
  Type 'X[K] & null' is not assignable to type 'Required<X>[K]'.
    Type 'X[K] & null' is not assignable to type 'never'.

我猜 function 中有錯誤(可能與Required的使用有關),但我無法解決。

謝謝你。

當您測試v !== undefined TypeScript 時,會將v的類型縮小為X[K] & ({} | null) 此交集類型使用交集從值類型中排除未定義。

Required<X>[K]做類似的事情,但實際上有一個極端情況,當屬性類型包含undefined時,它不會從K中刪除undefined ,但該屬性不是可選的:

//number | undefined
type XX = Required<{ o: undefined | number }>['o']

游樂場鏈接

即使Required<X>[K]X[K] & ({} | null)更寬松(允許X[K] - optional undefined )TypeScript 將無法按照映射類型得出此結論。

最簡單的解決方案是定義一個NotUndefined undefined,類似於 TypeScript 從v中排除undefined的方式,我們可以將其用於返回值和defautlValue參數:

type NotUndefined<T> = T & ({} | null)

function get<K extends keyof X>(k: K, x: X, defaultValue: NotUndefined<X[K]>): NotUndefined<X[K]>  {
  const v = x[k];
  return v !== undefined ? v : defaultValue;
}

游樂場鏈接

如果該屬性是必需的,並且它的類型中顯式undefined ,則上面的版本不允許默認值undefined (例如{ d: boolean | null | undefined; } )。

您可以保留原始行為,方法是將defaultValue恢復為Required<X>[K]並將其添加到與NotUndefined<X[K]>的聯合中以返回類型:

function get<K extends keyof X>(k: K, x: X, defaultValue: Required<X>[K]): Required<X>[K] | NotUndefined<X[K]>  {
  const v = x[k];
  return v !== undefined ? v : defaultValue;
}

游樂場鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM