不应该使用?Function
?作为类型。它表示任何函数。
通常,您希望更具体-例如指定参数的数量或函数返回的内容。
如果您确实希望表示一个可以接受任意数量的参数并返回任何类型的函数,请使用(...args: any[]) => any
?。
让我们想象一下,你正在创建一个函数,它汇总了一个对象数组。这里有一个例子,取自excaldraw代码库:
const sum = <T>(
array: readonly T[],
mapper: (item: T) => number
): number =>
array.reduce(
(acc, item) => acc+ mapper(item),
0
);
让我们看一下类型定义。这个函数接受:
?readonly T[]
映射函数:?(item: T) => number
返回?number
?。
在代码体中,它调用array.reduce(func, 0)
。这意味着函数中的?acc
?从?0
?开始。
对于数组的每个成员,它将?acc
?和?mapper(item)
?加在一起。最后得到的是数组中所有元素的和。
?
?mapper
?函数是关键。让我们把它剥开来看一看:
type Mapper<T> = (item: T) => number;
让我们想象一下这个用例:
interface YouTubeVideo {
name: string;
views: number;
}
const youTubeVideos: YouTubeVideo[] = [
{
name: "My favorite cheese",
views: 100,
},
{
? name: "My second favorite cheese (you won't believe it)",
views: 67,
},?
];
const mapper: Mapper<YouTubeVideo> = (video) => {?
return video.views;
};
const result = sum(youTubeVideos,mapper); // 167
这里,?mapper
?表示从对象中提取数字的函数。?sum
?函数的强大之处在于,你可以放弃大多数类型声明:
const youTubeVideos = [
{name: "My favorite cheese",views: 100 },
{
name: "My second favorite cheese (you won't believe it)",
views: 67,
},
];
const result = sum(youTubeVideos, (video) => {
return video.views;
}); // 167
实际上我们已经丢弃了所有的类型声明,但是?video
?仍然被推断为?{ name: string; views: number }
?。这是可能的,因为函数定义的特殊性:?(item: T) => number
?。
Function
?呢?我看到很多新手开发者犯的一个大错误是用?Function
?类型声明像?mapper
?这样的函数:
const sum = <T>(
array: readonly T[],
mapper: Function
): number =>
array.reduce(
(acc, item) => acc+ mapper(item),
0
);
这个关键字基本上代表“任何函数”。这意味着?sum
?在技术上可以接收任何函数。
当在?sum
?中使用时,我们失去了?(item: T) => number
?提供的很多安全性:
TypeScript现在不能推断出?item
?应该是什么,或者我们的mapper函数应该返回什么。
这里的教训是“不要使用?Function
?”——总是有更具体的选项可用。
有时候,你会想要在TypeScript中表达“任意函数”。为此,让我们来看看TypeScript的一些内置类型,Parameters
?和?ReturnType
?。
export type Parameters<
T extends (...args: any) => any
> = T extends (...args: infer P) => any
? P
: never;
?
export type ReturnType<
T extends (...args: any) => any
> = T extends (...args: any) => infer R ? R : any;
您将注意到这两个实用程序类型使用相同的约束:?(...args: any) => any
?。
(...args: any)
?表示函数可以接受任意数量的实参,?=> any
?表示它可以返回任何值。
要表达一个没有参数的函数(但会返回任何值),你需要使用?() => any
?:
在表示类型时不应该使用Function
?。
(a: string, b: number) => any
?语法可用于只指定参数而不指定返回类型的情况。
(...args: any) => any 可以用来表示任何函数类型。
?欢迎关注公众号:文本魔术,了解更多