原文链接:https://www.totaltypescript.com/dont-use-function-keyword-in-typescript
翻译:一川
在Typescript中不应该使用Function
作为一个类型 , 因为它可以表示任何函数 。通常,我们期望的是更具体的类型--例如指定参数的数量或函数返回的内容 。如果确实要表示可以接受任意数量的参数并返回任何类型的函数 , 请使用 (...args: any[]) => any
。
1完整的解释假设您正在创建一个汇总对象数组的函数 。这是一个 , 取自Excalidraw代码库:
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对于数组的每个成员,它通过将
acc
和mapper(item)
进行相加 , 最终得到数组所有成员的总和 。2什么可以用来作为函数声明?
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
3关于什么是函数?我看到很多初学者开发人员犯的一个大错误 , 声明一个类似于 mapper和Function类型 的函数:const sum = <T>( array: readonly T[], mapper: Function): number => array.reduce( (acc, item) => acc + mapper(item), 0 );
这个关键字基本上代表“任何函数” 。这意味着从技术上讲可以 sum 接收任何函数 。当在 中使用 sum 时,我们失去了很多
(item: T) => number
提供的安全性:const result = sum(youTubeVideos, (item) => { // Parameter 'item' implicitly has an 'any' type. // We can return anything from here, not just // a number! return item.name;});
TypeScript 现在无法推断应该是什么 item,或者我们的mapper函数应该返回什么 。这里的教训是“不要使用 Function ” - 总有一个更具体的选项可用 。
4表示“任何函数”有时 , 期望在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
表示它可以返回任何内容 。5表示没有参数的函数要表达一个没有参数的函数(但返回任何内容),您需要使用
() => any
:const wrapFuncWithNoArgs = (func: () => any) => { try { return func(); } catch (e) {}}; wrapFuncWithNoArgs((a: string) => {});> Argument of type '(a: string) => void' is not assignable to parameter of type '() => any'.> Target signature provides too few arguments. Expected 1 or more, but got 0.
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ChatGPT不是唯一:自动编写程序的另七个选择!
- 香蕉怎么存放保鲜长 香蕉怎么存放保鲜长久不坏
- 《伪装者》女主开撕胡歌!被撞断锁骨还不让说,遭网暴10年难以忍受
- 微信这个地方可以查看对方和谁关系不一般,操作简单,一看就能学会
- 人设崩塌, 冯小刚金屋藏娇20年, 绝代风华, 自曝这辈子最对不起的就是徐帆
- 曝汪小菲给大S巨额达成和解,拒绝和玥儿一起过中秋,称以后不相欠
- 娱乐圈到底有多乱?“潜规则”真是无处不在,国际巨星也得如履薄冰
- 不粘锅起泡是怎么回事 不粘锅起泡是什么原因
- 当红女星穿中式衣冠不整,扣子没系裤腿脏,和老外勾肩搭背惹争议
- 港媒称黄日华求婚女神,妻子去世只有三年,说好的终生不娶呢?