不要在TypeScript中使用Function类型

发布时间:2024年01月12日

  • 不应该使用?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 可以用来表示任何函数类型。


?欢迎关注公众号:文本魔术,了解更多

文章来源:https://blog.csdn.net/wannianchuan/article/details/135542717
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。