簡體   English   中英

如何定義一個只接受可能是打字稿類型的參數的函數?

[英]How to define a function which only accepts parameters which may be a type in typescript?

我想定義一個函數,如:

function isNumber(param: ???): param is number {
}

如果參數可能是一個數字,例如number | string number | stringnumber | boolean number | boolean ,它可以傳遞給函數。 如果不是,例如它的類型是stringboolean ,就會出現編譯錯誤。

是否可以定義這樣的類型?

從概念上講,您希望isNumber()param的類型T中通用,但您希望T下限number 這與被認為是上限的正常extends 約束相反。 不幸的是,TypeScript 不直接支持下界泛型。 這是在microsoft/TypeScript#14520中請求的,如果它曾經實現過,它可能會使用super而不是extends並且看起來像

// NOT VALID TS (as of 4.7), DON'T DO THIS
function isNumber<T super number>(param: T): param is number {
  return typeof param === "number"
}

但是,正如我所說,我們不能這樣做。


相反,我們可以通過在條件類型上使用常規上限來模擬下界泛型。 T extends (U extends T ? unknown : never)這樣的東西會表現得有點像T super U 如果TU的超類型,則(U extends T ? unknown : never)計算結果為unknown ,因此滿足約束 ( T extends unknown )。 否則, (U extends T ? unknown : never)的計算結果為never ,因此可能不滿足約束 ( T extends never )(除非T never自身,無法通過這種方式進行防范)。

在您的情況下,如果Tnumber的超類型或子類型,我們實際上很好,所以我們可以寫T extends (number extends T ? unknown : number)並且如果T恰好是像14這樣的數字文字類型,那么一切仍然作品。

一個問題是編譯器不明白param可能是number的超類型,所以你不能返回類型謂詞param is number 相反,您需要編寫編譯器認為可分配給T (和number )的類型。 所以我們將使用交集param is T & number

所以這里是:

function isNumber<T extends number extends T ? unknown : number>(
  param: T
): param is number & T {
  return typeof param === "number"
}

讓我們測試一下:

isNumber("oops"); // error, Argument of type 'string' is 
// not assignable to parameter of type 'number'.
isNumber(Math.random() < 0.5 ? "abc" : 123); // okay
isNumber(14); // okay

看起來不錯。

Playground 代碼鏈接

暫無
暫無

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

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