操場
我試圖使未定義的值是可選的,而非可選的值是可選的。我的完美例子是:
type TypeObj = {
a: undefined;
b: number;
c: string;
}
call("a"); call("b", 1); call("c", "3"); // should work
call("b", "a"); call("c", 3) // shouldn't work
call("b"); call("c") // also shouldn't work
但是我目前的方法(第二個引數是可選的)允許call在沒有第二個引數的情況下使用 b 和 c,這是我不想要的。
function call<K extends keyof TypeObj = keyof TypeObj>(key: K, param?: TypeObj[K]) {
}
call("a"); call("b", 1); call("c", "3"); // works (good)
call("b", "a"); call("c", 3) // doesn't work (good)
call("b"); call("c") // works (don't want that)
uj5u.com熱心網友回復:
這種事情本質上需要call()有多個呼叫簽名。傳統上,這需要您創建call()一個多載函式,但您也可以通過讓函式接受元組型別的剩余引數來實作。
這是一種方法:
type OptionalIfUndefined<T> =
undefined extends T ? [param?: T] : [param: T];
function call<K extends keyof TypeObj>(
key: K, ...[param]: OptionalIfUndefined<TypeObj[K]>
) {
const _param = param as TypeObj[K]; // <-- might need this
}
該OptionalIfUndefined<T>型別是一個條件型別,用于檢查是否undefined可分配給T。如果是這樣,它評估為一個帶有可選元素型別T的單元素元組;否則,它評估為具有所需元素型別的單元素元組T。
然后call()給定一個型別為 的 rest 引數OptionalIfUndefined<TypeObj[K]>。我們使用解構賦值,所以這param是一個保存單個元素的變數名,因為這就是我們真正想要的(保存它的實際陣列對我們沒有用)。
在您的示例中,您在 的實作中沒有做任何事情call(),但是如果您期望param被稱為 typeTypeObj[K]您會感到失望。泛型條件型別對編譯器本質上是不透明的,因此它不知道typeof param會比TypeObj[K] | undefined. 如果您需要這樣的功能,您需要像這樣斷言它const _param = param as TypeObj[K],然后使用_param而不是(或交換名稱)。param
好吧,讓我們確保它有效:
call("a") // okay
call("a", undefined) // okay
call("b", 1); // okay
call("b") // error
call("c", "a"); // okay
call("c") // error
看起來不錯!
Playground 代碼鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/484018.html
標籤:打字稿
上一篇:熱多載時CDK未檢測到lambda的typescript檔案
下一篇:Button'型別中的屬性'fit'不能分配給基本型別'IButton'中的相同屬性。型別“字串”不可分配給型別“適合”
