慎用!!!不要在Typescript中使用Function类型
创始人
2025-07-02 16:41:17
0

原文链接:https://www.totaltypescript.com/dont-use-function-keyword-in-typescript

翻译:一川

在Typescript中不应该使用Function作为一个类型,因为它可以表示任何函数。通常,我们期望的是更具体的类型--例如指定参数的数量或函数返回的内容。如果确实要表示可以接受任意数量的参数并返回任何类型的函数,请使用 (...args: any[]) => any。

1、完整的解释

假设您正在创建一个汇总对象数组的函数。这是一个,取自Excalidraw代码库:

const sum = (
  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 = (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 = (video) => {
  return video.views;
};
 
const result = sum(youTubeVideos, mapper); // 167

3、关于什么是函数?

我看到很多初学者开发人员犯的一个大错误,声明一个类似于 mapper和Function类型 的函数:

const sum = (
  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.

6、总结

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 。

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
30分钟搞定iOS自定义相机 最近公司的项目中用到了相机,由于不用系统的相机,UI给的相机切图,必须自定义才可以。就花时间简单研究...
Intel将Moblin社区控... 本周二,非营利机构Linux基金会宣布,他们将担负起Moblin社区的管理工作,而这之前,Mobli...