在接口中使用胖箭头和非胖箭头语法声明函数有啥区别?

Posted

技术标签:

【中文标题】在接口中使用胖箭头和非胖箭头语法声明函数有啥区别?【英文标题】:What's the difference between declaring functions using the fat arrow and non-fat arrow syntax in interfaces?在接口中使用胖箭头和非胖箭头语法声明函数有什么区别? 【发布时间】:2021-06-23 02:01:01 【问题描述】:

在 TypeScript 的接口和类型中使用胖箭头和非胖箭头语法声明函数有什么区别?

例如:

build(paramOne: string): string;

相比:

build: (paramOne: string) => string;

起初,我认为它会限制我实现功能的方式,但事实并非如此。所以,我认为它与 ES6 中的 this 无关。但我确实注意到,当我尝试重载时,以粗箭头语法声明的那个有问题。

例如,这是不可接受的:

build: (paramOne: string) => void
build: (paramOne: number, paramTwo: string) => void

这会报错:

Subsequent property declarations must have the same type. Property 'build' must be of type ' (paramOne: string): string; (paramOne: number, paramTwo: string): number; ', but here has type '(params: unknown) => void

但这没关系:

build(paramOne: string): string;
build(paramOne: number, paramTwo: string): number;

那么,这两种语法是否相同?有什么区别或场景我应该使用一个而不是另一个?

【问题讨论】:

【参考方案1】:

主要区别在于带箭头语法的是function type expression,而另一个是call signature。明显的区别是语法,来自手册:

请注意,与函数类型表达式相比,语法略有不同 - 在参数列表和返回类型之间使用 : 而不是 =>。

您是正确的,此语法不会使函数的 this 成为词法范围。您可以指定任何 this 类型,您希望函数在调用时具有:

thisChanged: (this:  test: number , param1: number, param2: boolean) => string;

但正如您也正确猜到的那样,应用程序存在细微差别。请注意术语表达式,而不是签名。前者“评估”到一个调用签名,除非定义为表达式的交集,而后者可以定义多次以创建function overloads:

//multiple call signatures used for function overloading:
function build(param1: string) : string;
function build(param1: number) : string;
function build(param1: string | number) 
    return param1.toString();


//intersection of expressions 
type build2 = ((param1:string) => string) & ((param1:number) => string);

declare const b: build2;
b(2) //OK
b("test") //OK
b(false) //No overload matches this call.

应用于您在object types 中使用它们的用例,可以在同一个键下多次指定调用签名,因为这会导致多个函数重载。另一方面,[key]: <function expression> 语法定义了一个具有函数表达式类型值的属性(因此无法多次指定该属性,因为键必须是唯一的)。

还要注意,推断的类型对应于函数的定义方式(作为函数声明或表达式):

//call signature: function build3(param1: string | number): string
function build3(param1: string|number) : string 
    return param1.toString();


//function expression: const build4: (param1: string | number) => string
const build4 = (param1: string|number) : string => param1.toString();

Playground

【讨论】:

以上是关于在接口中使用胖箭头和非胖箭头语法声明函数有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

对类方法使用胖箭头语法时,我可以使用 TypeScript 重载吗?

js 的胖箭头问题

如果在胖箭头函数内

如何在 CoffeeScript 胖箭头回调中引用实际的“this”?

ES6笔记————let,箭头函数,剩余参数

JavaScript ES6箭头函数指南