![](/img/trans.png)
[英]How to overload a function with multiple parameters correctly in typescript?
[英]How to use Typescript Function Overloading with a function that has multiple parameters?
我有一個函數試圖在數字數組中找到一個值。 該值可以是一個對象或一個數字。 如果值是一個對象,則有一個“key”屬性用於從對象中獲取數字值。
我正在嘗試使用Function Overloading
來擁有一個可以處理這兩種情況的函數。
type ObjectType = {
[key: string]: number
}
type FunctionType = {
<T extends ObjectType>(v: T, list: number[], key: string): T | undefined
(v: number, list: number[]): number | undefined
}
const find: FunctionType = <T extends ObjectType | number,>(v: T, list: number[], key?: string)=>{
const value = typeof v === 'number' ? v : v[key]
return list.find((item)=>{
return item === value
})
}
這會產生錯誤Type undefined cannot be used as an index type
但是在這個分支中,v的值是一個對象,那么key怎么沒有定義呢?
謝謝
Alex Wayne 提出了一個解決方案,但它沒有正確地將值縮小到一個數字。
如果我們不調用 list.find,而是調用一個只接受數字的自定義函數,typescript 會拋出錯誤
const findNumber = (v: number, list: number[])=>{
/* Do stuff with v as a number */
return list.indexOf(v)
}
const find: FunctionType = <T extends ObjectType | number>(v: T, list: number[], key?: keyof T)=>{
const value = (key && typeof v === 'object') ? v[key] : v
return list[findNumber(value, list)]
}
“ObjectType”類型不能分配給“number”類型
實現函數不知道它的重載是什么。 這意味着如果重載函數簽名被刪除,重載函數實現必須仍然完全有效。
因此,雖然如果typeof v === 'number'
然后typeof key === 'string'
編譯器不知道這一點是正確的。
如果你純粹看這個函數簽名:
<T extends ObjectType | number,>(v: T, list: number[], key?: string)=>{
然后你會看到find({ someKey: 1 }, [1,2,3])
是一個有效的調用。 重載阻止了該調用,但該函數在沒有這些重載的情況下也必須有效。
這意味着要解決此問題,您必須在使用之前測試key
是否存在。
const value = (key && typeof v === 'number') ? v : v[key]
然而,這又帶來了一個新問題:
Type 'undefined' cannot be used as an index type.(2538)
我相信這是因為typeof v === 'number'
不夠細化。 我不確定它認為它可能是什么,但如果你反轉三元並通過typeof v === 'object'
打字稿進行優化,那么它會很高興。
const value = (key && typeof v === 'object') ? v[key] : v
最后,您可以在這里使用key: keyof T
來提高類型安全性。
const find: FunctionType = <T extends ObjectType | number>(v: T, list: number[], key?: keyof T)=>{
const value = (key && typeof v === 'object') ? v[key] : v
return list.find((item)=>{
return item === value
})
}
首先,讓我們確保無效狀態是不可表示的。 讓我們定義聯合類型:
type IsObj<T> = {
value: T, key: keyof T
}
type IsNumber = { value: number }
type Params<T> = IsObj<T> | IsNumber
您可能已經注意到,我綁定了第二個和第三個參數。
現在,我們可以定義我們的自定義類型保護:
const isNumber = <T,>(params: Params<T>): params is IsNumber => typeof params.value === 'number'
讓我們把它放在一起:
type ObjectType = {
[key: string]: number
}
type IsObj<T> = {
value: T, key: keyof T
}
type IsNumber = { value: number }
type Params<T> = IsObj<T> | IsNumber
const isNumber = <T,>(params: Params<T>): params is IsNumber => typeof params.value === 'number'
type FunctionType = {
<T extends ObjectType>(list: number[], params: IsObj<T>): T | undefined
(list: number[], params: IsNumber): number | undefined
}
const find: FunctionType = <T extends ObjectType | number,>(list: number[], params: Params<T>) => {
const value = isNumber(params) ? params.value : params.value[params.key]
return list.find((item) => item === value)
}
const result = find([1, 2, 3], { value: 42}) // ok
const result_ = find([1, 2, 3], { value: { age: 2 }, key: 'age' }) // ok
const result__ = find([1, 2, 3], { value: { age: 2 }, key: 'name' }) // expected error
const result___ = find([1, 2, 3], { value: 42, key: 'name' }) // expected error
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.