為什么 TS 不推斷此函式中的可選引數,因為undefined它在呼叫中被省略?
function fooFunc<T extends number | undefined>(param?: T){
let x: T extends undefined ? null : T
x = param ?? null as any
return x
}
如果顯式傳遞,它會按預期作業,undefined但如果只是省略引數則不會:
const fooResult1:number = fooFunc(3)
const fooResult2:null = fooFunc(undefined) // <-- this works
const fooResult3:null = fooFunc() // <-- this doesn't; it infers null | number, not null
如果我將約束擴大到包括unknown, ie, <T extends number | undefined | unknown>,事情會按預期作業,但這不是一個很好的解決方案,因為在實際代碼中unknown會導致其他問題。
這里發生了什么,是否有修復/解決方法?
操場
更新
看起來我的問題的“為什么”部分的答案可能是 - 它就是這樣。請參閱@jcalz 的這個 SO 答案。所以我想我的問題是真的有什么辦法可以解決它,還是我只需要沿著除錯的道路走下去,為什么unknown稍后在我的代碼中給我帶來問題?
更新 2(修訂)
這是我的問題——unknown如果我將上面的函式更改為
function fooFunc<T extends number | undefined | unknown>(param?: T){
let x: T extends undefined ? null : T
x = param ?? null as any
return x
}
那么它就起作用了,從某種意義上說,null如果在沒有引數的情況下呼叫它,它將正確回傳一個型別,即fooFunc(). 但問題是它現在也將允許使用任意引數呼叫自己,例如fooFunc("hello"),這不是所需的行為。
現在,你可能會說,那只是因為你總是可以在 JS 中添加額外的引數,但這不是這里發生的事情,因為如果泛型嵌入到一個物件中,也會發生同樣的問題,即,
function bazFunc<T extends number | undefined | unknown>(param: {a: number; b?: T}){
let x: T extends undefined ? null : T
x = param.b ?? null as any
return x
}
bazFunc({a:1, b:"hello"}) // <-- I don't want this
精致的游樂場
編輯 3
我將@kaya3 的答案標記為已接受,因為我相信它準確地確定了問題的根源,即函式開頭的條件型別是分布式的,因此解決了應用于和的條件的聯合. 建議的解決方案——使用多載——在許多情況下似乎也不錯。numberundefined
它在我的情況下不起作用,因為我需要回傳型別推斷。但是,使用覆寫默認的條件分配行為[]確實有效。因此,問題中問題的替代解決方案是這樣的,它可以按我的意愿作業:
function fooFunc<T extends number | undefined>(param?: T){
let x: [T] extends [number] ? T: null
x = param ?? null as any
return x
}
const fooResult1:number = fooFunc(3)
const fooResult2:null = fooFunc(undefined)
const fooResult3:null = fooFunc()
通過使用方括號不分配條件,它現在僅決議為非未定義情況下 T 的實際值,這是我在特定實體中想要的。
uj5u.com熱心網友回復:
unknown此處未推斷缺少的型別引數;通過將滑鼠懸停在函式呼叫上,我們可以看到型別引數被推斷為上限number | undefined。因此回傳型別T extends undefined ? null : T,它是一個分布式條件型別,決議為,number | null因為number部分映射到number和undefined部分映射到null。所以在第三個例子中,函式的回傳型別是number | null,它不能分配給 type null,因此是錯誤的。
在這種情況下-當你有一個可選的引數的通用功能,但它才有意義是通用在引數是現在-我認為最明智的解決辦法是使用函式多載。然后,您可以直接指定在不帶引數呼叫時希望回傳型別是什么,同時在帶引數呼叫時仍然讓它是通用的。
// overload for calling with no argument
function fooFunc(): null;
// overload for calling with one argument
function fooFunc<T extends number | undefined>(param: T): T extends undefined ? null : T;
// actual implementation
function fooFunc<T extends number | undefined>(param?: T) {
let x: T extends undefined ? null : T
x = param ?? null as any
return x
}
游樂場鏈接
uj5u.com熱心網友回復:
試試這個....
function fooFunc<T extends number | undefined>(param?: T){
// let x: T extends undefined ? null : T
let x = param ?? null as any
return x
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/405758.html
標籤:
上一篇:ngx-translate:檢測語言變化的事件(Angular)
下一篇:條紋支付頁面連接不安全問題
