不要在TypeScript中使用Function类型

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


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

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值