尽早提高警惕:TypeScript 中显式返回类型的威力

作为开发人员,我们总是在寻找在错误进入生产之前防止错误的方法。TypeScript 可以成为您的朋友的方法之一是使用显式返回类型注释。这个看似简单的功能可以显著提高代码的可靠性并提供更好的开发人员体验,尤其是对于 API、实用程序函数或库的使用者而言。

隐性回报的微妙陷阱

考虑一个看起来很无害的函数:

function getUserStatus(lastLogin: Date) {
  const daysSinceLogin =
    (Date.now() - lastLogin.getTime()) / (1000 * 60 * 60 * 24);

  if (daysSinceLogin < 7) {
    return "active";
  }

  if (daysSinceLogin < 30) {
    return "inactive";
  }
}

乍一看,这个函数似乎没问题。但有一个隐藏的问题:如果条件不满足,函数将隐式返回“undefined”。这可能会导致难以追踪的运行时错误。此外,TypeScript 不会在函数定义时引发错误,而只会在调用点引发错误。

您可以理解,对于使用您的代码的开发人员来说,这是多么令人沮丧。那么显式返回类型在这里能有什么帮助呢?

显式返回类型的魔力

通过添加显式的返回类型,TypeScript 将在函数定义时立即引发红色警报:

function getUserStatus(lastLogin: Date): "active" | "inactive" | "dormant" {
  const daysSinceLogin =
    (Date.now() - lastLogin.getTime()) / (1000 * 60 * 60 * 24);

  if (daysSinceLogin < 7) {
    return "active";
  }

  if (daysSinceLogin < 30) {
    return "inactive";
  }
}

如果你将此代码输入到 TypeScript Playground,你将立即看到一个错误:

函数缺少结束返回语句并且返回类型不包含“undefined”。

作为此功能的作者,您现在可以主动解决此问题。

function getUserStatus(lastLogin: Date): "active" | "inactive" | "dormant" {
  const daysSinceLogin =
    (Date.now() - lastLogin.getTime()) / (1000 * 60 * 60 * 24);

  if (daysSinceLogin < 7) {
    return "active";
  }

  if (daysSinceLogin < 30) {
    return "inactive";
  }

  return "dormant";
}

为什么这很重要

其好处是直接而显著的:

  • 早期错误检测:TypeScript 将在函数定义处而不是调用处突出显示问题。
  • 强制完整性:通过指定返回类型,您实际上是在创建函数必须履行的合同。TypeScript 将成为您的代码审阅者,确保您处理所有可能的情况。
  • 提高代码可读性:显式返回类型可用作文档。它们清楚地传达了函数预期返回的内容。
  • 更新:2024 年 12 月 11 日

    一位读者 (Pierre Spring) 在 Mastodon 上提醒我,你可以配置 TypeScript 以防止你不定义返回。你可以在 `tsconfig.json` 文件中将 `noImplicitReturns` 标志设置为 `true` 来实现这一点。

    {
      "compilerOptions": {
        "noImplicitReturns": true
      }
    }

    在 TypeScript 文档中了解有关此标志的更多信息。

    功劳归功劳

    这种方法的灵感来自 Mike North 在 Frontend Masters 上的 TypeScript 课程。它证明了细微的、有意为之的类型选择可以显著提高代码质量和可用性。

    结论

    定义显式返回类型不仅仅是 TypeScript 的一项功能;它鼓励您仔细考虑所有可能的代码路径,明确您的意图,并在潜在问题成为痛点之前将其捕获。