在 Typescript 中注释函数

Meme Image

在 TypeScript 中注释函数的最基本方式是这样的

function add(a: number, b: number): number{
 // logic
}

// or

const add = (a: number, b: number): number => {
    //logic
}

**可选参数用问号 param? 注释,像这样**

function optional(a: number, b?: number){
    console.log(a)
}

但是**回调函数**,或者参数类型和返回类型相关的函数呢()。

函数值

观察此 JavaScript 函数

function multiplier(factor){
    return value => factor * value
}

这样我们就可以像这样使用该函数;

const n  = multiplier(6)
n(8) // 48

函数值在 TypeScript 中的注释如下

(param1: type, param2: type)=> type

// or

const add: (a: number, b: number)=> number = function (a, b){
    return a + b
}

因此,为了注释“乘数”函数,我们有

function multiplier(factor: number): (value: number) => number{
    return value => factor * value
}

你的 IDE(最好是 VSCode)将自动推断函数逻辑中的“值”的类型()

泛型函数

此函数注释错误

function pickFirst(array: Array): T{
    return array[0]
}

当然,这会引发一个错误

`无法找到名称 T`

因此,注释泛型函数的格式为

function fnName (param: T): U{
    //logic
}

观察通用名称的声明位置。因此,正确注释上述函数;

function pickFirst(array: Array): T{
    return array[0]
}

**现在可以了。**

**但是具有函数参数的通用函数怎么办**。

例如,我们想要注释一个名为“myMap”的自定义“map”函数,它在 Javascript 中是这样写的

function myMap(arr, fn){
    rreturn arr.map(fn)
}

我们可以像这样注释

function myMap(arr: Input[], fn: (item: Input, index?: number) => Output): Output[]{
    return arr.map(fn)
}

我们应该在上面的代码片段中注意的是,`fn` 函数接受与 `Input` 数组相同类型的项并返回 `Output` 类型。

**静态 Array.from() 方法怎么样?**

function myFrom(iterable: Iterable): Array{
    // logic
}

**或者 array.filter() 方法?**

function myFilter(arr: Input[], fn: (item: Input) => boolean): Input[]{
    return arr.filter(fn)
}

通用约束

您还可以将泛型变量限制为具有特定属性的类型。例如,

function pickInnerFirst(array: Array): T{
    return array[0][0]
}

此函数选取二维数组中的第一个元素

这确保它只适用于数组和字符串()

pickOne([12, 20, 30]) // wont work.

我们还可以使用**接口**

interface Lengthly{
    length: number;
}

function pickInnerFirst(array: Array): T{
    return array[0][0]
}

函数接口

如果你不知道的话,**函数是对象**,并且它们具有属性

const add = (a, b) => a + b

console.log(add.toString()) //(a, b) => a + b

// also
console.log(Object.getPrototypeOf(add) == Function.prototype) //true
console.log(Object.getPrototypeOf(Function.prototype) == Object.prototype) //true

第二个例子表明“add”函数是“Object.prototype”()的子函数,因此是一个对象。

**有趣的是**你可以在 JavaScript 中将属性附加到函数

function shout(fn, value){
    fn(value)
    console.log(fn.description)
} 

function hey(value){
    console.log(value)
}

hey.description = `A function called ${hey.name}` // A

shout(hey, "Hola!!!")

此代码片段将返回

>> Hola!!!
>> A function called hey

请注意,在**A**处,我们为函数附加了一个名为“description”的属性,这只有通过**对象**才有可能实现。

也就是说得出结论;

对象可以用接口 () 来描述。对于函数,这也是可能的。但是,**只有在向函数添加特殊属性时才需要考虑这一点。**

interface describableFunction{
    (value: string): void; //A
    description: string;
}

在注释**A**中我们描述了函数的参数和返回类型。

因此,要在 TypeScript 中注释早期的代码,

interface describableFunction{
    (value: string): void;
    description: string;
}

function shout(fn: describableFunction, value: string) { //A
    fn(value)
    console.log(fn.description)
}

function hey(value: string) {
    console.log(value)
}

hey.description = `A function called ${hey.name}`
shout(hey, "Hola!!!")

观察我们在 A 处的 `shout` 函数中使用接口的方式。

为什么我应该了解如何在 Typescript 中注释函数?

嗯,它有助于构建更智能的类型系统,从而减少出现错误的机会。如果您正在构建库或框架,则可能必须使用此处提到的部分或大部分概念。

如果您只是使用库,那么这些概念并不是真正必要的,即使它们可以让您更深入地了解您正在使用的库。

**如果您有任何疑问或本文中有错误,请在下面的评论中分享⭐**