首页 前端知识 TypeScript - 函数(上)

TypeScript - 函数(上)

2024-09-03 02:09:36 前端知识 前端哥 224 645 我要收藏

目录

1、介绍 

2、函数类型表达式

3、呼叫签名

4、构造签名

5、泛型函数

6、推论

7、约束

8、使用约束值

9、指定类型参数


1、介绍 

函数是JavaScript应用程序的基础。 它帮助你实现抽象层,模拟类,信息隐藏和模块。 在TypeScript里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义 行为的地方。函数是任何应用程序的基本构建块,无论它们是本地函数、从其他模块导入的函数,还是类上的方法。 它们也是值,就像其他值一样,TypeScript 有很多方法来描述如何调用函数。 让我们学习如何编写描述函数的类型。

2、函数类型表达式

描述函数的最简单方法是使用函数类型表达式。 这些类型在语法上类似于箭头函数:

function Animal(fn: (age: number)=>void){
    return fn(20);
}

function Cat(age: number) {
    console.log('age: ', age);
}

// age:  20
Animal(Cat) 

语法(age: number) => void 表示“具有一个参数的函数,参数为数字类型,没有返回值”。 就像函数声明一样,如果未指定参数类型,则是隐式的 any 类型。

fn: (age: number)=>void 形成一个函数表达式,参数是必须的,需声明对应的类型,否则具有隐藏式的类型 any。

我们可以把函数类型表达式赋值给类型别名,如下所示:

type expFunc = (age: number) => void;

function Animal(fn: expFunc) {
    return fn(20);
}

function Cat(age: number) {
    console.log('age: ', age);
}

// age:  20
Animal(Cat) 

3、呼叫签名

在 JavaScript 中,函数除了可调用之外,还可以具有属性。 但是,函数类型表达式语法不允许声明属性。 如果我们想描述一些可以用属性调用的东西,我们可以在对象类型中写一个调用签名

type DescInfo = {
    desc: string;
    (args: number): number
};

function Animal(fn: DescInfo) {
    // 我是tom🐱今年2岁
    console.log(fn.desc + '今年' +fn(2) + '岁');
}

function Cat(age: number) {
    return age;
}
Cat.desc = "我是tom🐱";

Animal(Cat)

请注意,与函数类型表达式相比,语法略有不同 - 在参数列表和返回类型之间使用,而不是上面缩写的(fn: (age: number)=>void)这样。

4、构造签名

JavaScript 函数也可以与运算符一起调用。 TypeScript 将这些称为构造函数,因为它们通常会创建一个新对象。 您可以通过在呼叫签名前面添加关键字来编写构造签名new

type DescInfo = {
   new (args: number): Cat
};

function Animal(fn: DescInfo) {
    return new fn(20);
}

class Cat {
    age: number;
    constructor(age: number){
        this.age = age;
    }
}

console.log(new Cat(20).age);  // 20

某些对象,如 JavaScript 的对象,可以带或不带 . 您可以任意组合同一类型的调用和构造签名:

interface Animal {
    new(name: string, birthday: Date);
    (n?:number): number; 
}

5、泛型函数

通常编写一个函数,其中输入的类型与输出的类型相关,或者两个输入的类型以某种方式相关。

function Animals(array: any[]) {
    return array[1];
}

如果函数返回数组元素的类型会更好,例如:any 或者其他类型

在 TypeScript 中,当我们想要描述两个值之间的对应关系时,会使用泛型。 我们通过在函数签名中声明一个类型参数来做到这一点:

function Animals<Type>(array: any[]) : Type | undefined {
    return array[1];
}

在函数定义是,指定泛型Type,在返回的时候也指定对应类型 Type | undefined,这样返回的结果就会事先定义的范围,这样也使得结果更可控。

function Animals<Type>(array: any[]) : Type | undefined {
    return array[1];
}
console.log(Animals([1,2])); // 2

6、推论

我们不必在此示例中指定。 类型是由 TypeScript 推断的 - 自动选择的。

我们也可以使用多个类型参数。 例如

function Animals<Input, Output>(arr: Input[], func: (arg: Input) => Output) : Output[] {
    return arr.map(func)
}
Animals([1,2,3], (n)=>console.log(n)); // 1 2 3

7、约束

我们编写了一些可以处理任何类型的值的通用函数。 有时我们想关联两个值,但只能对某个值子集进行操作。 在这种情况下,我们可以使用约束来限制类型参数可以接受的类型类型。

function longest<Type extends { length: number }>(a: Type, b: Type) {
    if (a.length >= b.length) {
      return a;
    } else {
      return b;
    }
  }

  const longerArray = longest([1, 2], [1, 2, 3]);
  const longerString = longest("alice", "bob");
  const notOK = longest(123, 100);

// longest 指定类型必须有长度 ,字符串和数组都有长度,而数组没有length 

在此示例中,有一些有趣的事项需要注意。 我们允许 TypeScript 推断返回类型 。 返回类型推理也适用于泛型函数(longest)。

因为我们被限制为 ,所以我们被允许访问 和 参数的属性。 如果没有类型约束,我们将无法访问这些属性,因为这些值可能是没有 length 属性的其他类型的值。Type{ length: number }.length a b

和的类型是根据参数推断的。 请记住,泛型都是关于将两个或多个值与同一类型相关联!longerArraylongerString

8、使用约束值

function minimumLength<Type extends { length: number }>(
  obj: Type,
  minimum: number
): Type {
  if (obj.length >= minimum) {
    return obj;
  } else {
    return { length: minimum }; // 报错...
  }
}

发现else里面的return,报错了,如下所示: 

不能将类型“{ length: number; }”分配给类型“Type”。
"{ length: number; }" 可赋给 "Type" 类型的约束,但可以使用约束 "{ length: number; }" 的其他子类型实例化 "Type"。

如果返回是Type类型,可以调用函数试一下

const arr = minimumLength([1, 2, 3], 6);
console.log(arr.slice(0)); // [1, 2, 3]

如果把上面返回值改成obj,之后,上面代码是可以执行。

9、指定类型参数

TypeScript 通常可以在泛型调用中推断预期的类型参数,但并非总是如此。 例如,假设您编写了一个函数来组合两个数组:

function arrayConcat<Type>(arr1: Type[], arr2: Type[]): Type[] {
  return arr1.concat(arr2);
}

下面测试一下,传不同类型是否会报错提示:

console.log(arrayConcat([1,2,3], ['name']));  // 不能将类型“string”分配给类型“number”。
console.log(arrayConcat([1,2,3], [true]));    // 不能将类型“boolean”分配给类型“number”。
console.log(arrayConcat([1,2,3], [4, 5, 6]));    
console.log(arrayConcat([1,2,3], [undefined]));
console.log(arrayConcat([1,2,3], [null]));

根据以上测试结果,可以看出前2种会有对应错误提示。

如果能提前知道类型的参数,可以提前指定类型参数。如下所示:

console.log(arrayConcat<number | string>([1,2,3], ['name']));  
console.log(arrayConcat<number | boolean>([1,2,3], [true])); 

转载请注明出处或者链接地址:https://www.qianduange.cn//article/17524.html
标签
评论
发布的文章

jQuery Keyframes 使用教程

2024-09-18 02:09:01

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!