簡體   English   中英

如何在 Typescript 中返回 NonNullable 類型?

[英]How can I return a NonNullable type in Typescript?

我有類似於以下的代碼:

interface Stuff {
  foo: number | null;
  bar: string | null;
}

let stuff: Stuff;

function getStuff(): Stuff;
function getStuff<K extends keyof Stuff>(key: K): NonNullable<Stuff[K]>;
function getStuff<K extends keyof Stuff>(key?: K): Stuff | NonNullable<Stuff[K]> {
  if (key == null)
    return stuff;

  const value = stuff[key];
  if (value == null)
    throw new Error(`${key} is null`);

  return value;
}


const myStuff = getStuff('foo');

顯然,當你到達getStuff的最后一行時, getStuff value不能為nullundefined ,但 Typescript 給出了這個錯誤:

Type 'Stuff[K]' is not assignable to type 'Stuff | NonNullable<Stuff[K]>'.
  Type 'string | number | null' is not assignable to type 'Stuff | NonNullable<Stuff[K]>'.
    Type 'null' is not assignable to type 'Stuff | NonNullable<Stuff[K]>'.
      Type 'Stuff[K]' is not assignable to type 'Stuff'.
        Type 'string | number | null' is not assignable to type 'Stuff'.
          Type 'null' is not assignable to type 'Stuff'.(2322)

如果我刪除NonNullable ,那么它可以正常工作,但當然myStuff將需要一個空檢查,這是我在這里試圖避免的。 即我知道這里的value不能為null ,但是我如何正確地讓 Typescript 知道,沒有“作弊”,例如通過return value! ?


打字稿游樂場


基於已接受答案的解決方案

最終將以下 util 添加到我們的項目中,帶有斷言和輔助類型(因此我們可以在代碼中編寫Null而不是null | undefined一堆地方)

// util/null
type Null = null | undefined;

export default Null;

export function isNotNull<T>(value: T)
: value is NonNullable<T> {
  return value != null;
}

export function assertNotNull<T>(value: T, throwError: (value: T) => never)
: asserts value is NonNullable<T> {
  if (value == null) throwError(value);
}

您可以簡單地進行類型斷言 - return value as NonNullable<Stuff[K]> ,或者引入自定義類型保護。

您面臨的問題是 TS 沒有將您的控制流空檢查范圍縮小到NonNullable ,但是通過自定義類型保護您可以強制執行它。 考慮:

// type guard narrows to NonNullable
function isNonNullable<T>(a: T): a is NonNullable<T> {
  return a !== null
}
function getStuff(): Stuff;
function getStuff<K extends keyof Stuff>(key: K): NonNullable<Stuff[K]>;
function getStuff<K extends keyof Stuff>(key?: K): Stuff | NonNullable<Stuff[K]> {
  if (key == null)
    return stuff;

  const value = stuff[key];
  if (isNonNullable(value)) {
    return value;
  }
  throw new Error(`${key} is null`);
}

請注意isNonNullable是通用類型保護,您可以將其與任何其他值一起使用。


反向條件也將正常工作:

if (!isNonNullable(value)) {
  throw new Error(`${key} is null`);
}
return value;

暫無
暫無

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

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