TypeScript:函数作为参数与严格类型化——完整解析

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

TypeScript:函数作为参数与严格类型化——完整解析与示例

\n\n

你好,同行!如果你曾经用 JavaScript 编写过代码,并将一个函数传递给另一个函数(例如,传递给 setTimeout 或 Array.map),那么你已经熟悉了高阶函数的概念。但当涉及到 TypeScript 时,一个合乎逻辑的问题出现了:"我能否对我作为参数传递的函数进行严格类型化?"。答案是肯定的,并且这是该语言最强大的特性之一。

\n\n

在本文中,我们将探讨如何声明TypeScript 中的函数类型,如何将它们作为参数传递,以及如何避免在签名上出错。你将了解如何使代码不仅安全,而且具有自文档性。我们开始吧!

\n\n

顺便提一下,这个问题是 Stack Overflow 上最热门的问题之一(有数千次浏览)。所以,如果你想一劳永逸地弄明白——你来对地方了。

\n\n

为什么这很重要:严格类型化节省时间

\n\n

想象一下,你正在编写一个接受另一个函数(回调)的函数。没有类型,你可能会意外地传递一个参数数量错误或返回值类型错误的函数。TypeScript 在编译阶段就能捕获这些错误,而不是在运行时。这就像给你的代码上了一道保险。

\n\n

下面是一个没有类型就无法工作的例子:

\n\n
// JavaScript(无类型)——错误只会在运行时出现\nfunction processData(callback) {\n    const result = callback(10, 20);\n    console.log(result);\n}\n\n// 哎呀,传递了一个只有一个参数的函数\nprocessData((x) => x * 2); // NaN —— 因为第二个参数是 undefined
\n\n

使用 TypeScript,我们可以明确指定回调期望的签名:

\n\n
// TypeScript —— 编译阶段报错\nfunction processData(callback: (a: number, b: number) => number): void {\n    const result = callback(10, 20);\n    console.log(result);\n}\n\n// ✅ 正确\nprocessData((x, y) => x + y); // 30\n\n// ❌ 错误:类型 '(x: number) => number' 不能赋值给类型 '(a: number, b: number) => number'\n// processData((x) => x * 2);
\n\n

很酷,对吧?现在让我们来分解所有声明此类类型的方法。

\n\n

方法 1:内联签名(最简单)

\n\n

最直接的方法是在参数中直接指定函数签名。当函数参数只使用一次时,这很方便。

\n\n
// 一个接受另一个函数(两个数字并返回字符串)的函数\nfunction formatNumbers(\n    a: number,\n    b: number,\n    formatter: (x: number, y: number) => string\n): string {\n    return formatter(a, b);\n}\n\n// 使用\nconst result = formatNumbers(5, 10, (x, y) => `总和:${x + y}`);\nconsole.log(result); // "总和:15"
\n\n

优点:快速、直观。
\n缺点:如果签名重复,将不得不复制代码。

\n\n

方法 2:函数的类型别名(可复用)

\n\n

如果你在多个地方使用相同的签名,最好将其提取到类型别名中。这使代码更简洁且更易于维护。

\n\n
// 声明函数类型\ntype Callback = (error: Error | null, data: string) => void;\n\n// 接受 Callback 的函数\nfunction fetchData(url: string, callback: Callback): void {\n    // 模拟异步请求\n    setTimeout(() => {\n        if (url) {\n            callback(null, "数据已获取");\n        } else {\n            callback(new Error("URL 为空"), "");\n        }\n    }, 1000);\n}\n\n// 使用\nfetchData("/api/data", (err, data) => {\n    if (err) {\n        console.error("错误:", err.message);\n    } else {\n        console.log("成功:", data);\n    }\n});
\n\n

请注意:我们使用了 void 作为返回类型。这意味着该函数可以不返回任何值

博客

书籍推荐