Typescript 中的函数重载

2025-06-07

Typescript 中的函数重载

Typescript 是一种建立在 Javascript 之上的类型系统,其唯一目的是通过应用强类型安全性来保护您的应用程序。

借助 Typescript,您可以通过在构建时捕获错误来减少运行时错误。作为一名优秀的团队成员,在创建实用程序函数时创建强类型函数会很有帮助。这样做,自动补全和类型推断将在您的队友使用您的函数时为您提供帮助,并减少错误。

让我们通过一种称为函数重载的技术来看看如何实现这一点


在此示例中,我们旨在创建具有以下功能的函数:

  • 通过检查每个元素是否以指定的搜索参数开头来过滤字符串数组。 
  • 选择返回第一个匹配项或所有匹配的元素。 
  • 检查给定的字符串是否以搜索参数开头

下面的函数演示了如何实现这些条件:



function select(arr: string[] | string, search: string, firstOnly = false){
        // ^? string | boolean | string[] | undefined
  if(Array.isArray(arr)){
    return firstOnly 
            ? arr.find(a => a.startsWith(search))
            : arr.filter(a => a.startsWith(search))
  }else {
    return arr.startsWith(search);
  }
}


Enter fullscreen mode Exit fullscreen mode

注:实现细节不是本文的重点。

现在,让我们调用此函数来返回与搜索参数匹配的所有元素:



const names = ['toto', 'jack', 'robert'];
const t = filter(names, 'to');
//    ^? string | boolean | string[] | undefined


Enter fullscreen mode Exit fullscreen mode

问题:推断的返回类型是string | boolean | string[] | undefined。Typescript 无法将返回类型缩小到 string[],即使我们知道这是唯一可能的返回类型。

TypeScript 无法缩小类型

在第二个示例中,如果我们想使用函数检查给定的字符串是否与搜索参数匹配,Typescript 允许我们设置该firstOnly参数,但这在我们的情况下是无用且令人困惑的。


为了解决这些问题,我们可以重载filter函数。重载是指定义同一函数的多个版本,并使其具有不同的参数类型和返回类型。

在这个例子中,我们定义了三个不同版本的过滤函数:



function filter(arr:string[], search: string): string[];
function filter(arr:string[], search: string, firstOnly: true): string | undefined;
function filter(elt:string, search: string): boolean;

function filter(arr: string[] | string, search: string, firstOnly = false){
  if(Array.isArray(arr)){
    return firstOnly ? arr.find(a => a.startsWith(search)): arr.filter(a => a.startsWith(search))
  }else {
    return arr.startsWith(search);
  }
}


Enter fullscreen mode Exit fullscreen mode

第一个版本接受一个字符串数组和一个搜索参数,并返回一个匹配字符串的数组。第二个版本添加了一个firstOnly参数,当设置为 时true,仅返回第一个匹配的字符串,如果未找到匹配项,则返回 undefined。第三个版本接受一个字符串和一个搜索参数,并返回一个布尔值,指示该字符串是否以搜索参数开头。

函数的实现filter会将所有定义连接成一个。但是,这个组合定义不能直接在代码中使用。如果我们想filter以字符串作为第一个参数调用该函数,并以布尔值作为最后一个参数,则需要添加一个新的函数定义。

重载filter函数有几个好处:

  • firstOnly仅当第一个参数为数组时才可以设置该参数。
  • 根据函数的参数,推断的类型正确缩小。

例子:

自动完成导致的错误

该图显示了 Typescript 抛出的错误,因为我们已经设置了firstOnly参数,但我们的第一个参数是 a,string并且没有函数定义与此实现匹配。



const names = ['toto', 'jack', 'robert'];
const first = filter(names, 'to', true);
//    ^? string | undefined

const second = filter(names, 'to');
//    ^? string[]

const third = filter('toto', 'to')
//    ^? boolean


Enter fullscreen mode Exit fullscreen mode

函数调用具有良好的自动完成和类型推断功能,使得filter函数的使用更加容易。

警告:然而,仍然有一个重要的警告需要考虑。

虽然函数调用变得更加安全,但我们在实现内部却失去了所有类型安全性。TypeScript 告诉我们我们比它更了解类型,如果我们的定义不正确,TypeScript 就不会保护我们。

让我们用一个例子来说明这个警告,说明我们如何通过谎报功能的行为来欺骗我们的团队成员:



function lying(elt:string): number;
function lying(elt:number): string;

function lying(elt: string | number){
  return elt;
}


Enter fullscreen mode Exit fullscreen mode


const t = lying('toto');
//    ^? number


Enter fullscreen mode Exit fullscreen mode

上面的代码中,函数很简单,但却完美地演示了问题所在。我们设置了两个 TypeScript 信任的定义,但正如我们所见,返回类型不正确。调用该函数时,推断出的 t 类型不正确。

虽然函数重载非常有用,但务必谨慎,确保类型尽可能准确。有时候,类型准确度较低总比欺骗用户要好。


希望以上内容能帮助您了解 Typescript 中的函数重载!这确实是一项高级功能,但它在提升代码安全性和可靠性方面非常有用。记住,使用函数重载时务必谨慎,因为如果不谨慎使用,可能会导致类型安全问题。

祝你的 Typescript 项目一切顺利,如果有任何其他问题,请随时联系我!你可以在TwitterGithub上找到我。

文章来源:https://dev.to/this-is-angular/function-overloading-in-typescript-53eb
PREV
开始使用 spartan/ui - 类似 Shadcn 的 Angular UI 组件
NEXT
在 Angular 中创建自定义模块