[英]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.