原文链接:https://www.totaltypescript.com/dont-use-function-keyword-in-typescript
翻译:一川
在Typescript中不应该使用Function作为一个类型,因为它可以表示任何函数。通常,我们期望的是更具体的类型--例如指定参数的数量或函数返回的内容。如果确实要表示可以接受任意数量的参数并返回任何类型的函数,请使用 (...args: any[]) => any。
假设您正在创建一个汇总对象数组的函数。这是一个,取自Excalidraw代码库:
const sum = <T>( array: readonly T[], mapper: (item: T) => number): number => array.reduce( (acc, item) => acc + mapper(item), 0 );
让我们看一下类型定义。此函数包含:
并返回 number类型。
在主体中,它调用array.reduce(func, 0)。这意味着在acc
对于数组的每个成员,它通过将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和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 ” - 总有一个更具体的选项可用。
有时,期望在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:
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.
Function不应该用作表示函数类型。当您只想指定参数而不指定返回类型时,可以使用语法(a: string, b: number) => any。
记住,(...args: any) => any 可用于表示任何函数类型。
此处,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 。
本文链接:http://www.28at.com/showinfo-26-11839-0.html慎用!!!不要在Typescript中使用Function类型
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com