自学TS(三)

目录

数组的类型

类型 + 方括号

数组泛型

用接口表示数组

类数组

多维数组

数组在函数中的使用

函数的类型

函数声明

函数表达式

用接口定义函数的形状

可选参数

参数默认值

剩余参数

重载

箭头函数


数组的类型

        在 TypeScript中,数组类型有多种定义方式,比较灵活。

类型 + 方括号

        最简单的方式是使用[类型 + 方括号]来表示数组:

let arr: number[] = [1, 2, 3, 4, 5];

        上述例子中,规定了数组的类型为number,所以数组元素只能为number类型。

let arr: number[] = ["1", 2, 3, 4, 5];
// Type 'string' is not assignable to type 'number'.
// 类型'string'不能赋值给类型'number'。

        数组一些方法的参数也会根据数组在定义时的类型进行限制:

let arr: number[] = [1, 2, 3, 4, 5];
arr.push("6");
// Argument of type 'string' is not assignable to parameter of type 'number'.
// 'string'类型的参数不能赋值给'number'类型的参数。

        上述例子中,push方法只允许传入number类型的参数,但是最后缺传入了string类型的参数,所以报错了。

        当我们数组需要多个类型的时候可以使用联合类型或者任意类型来进行处理。

let arr: (number | string)[] = ["1", 2, "3", 4, "5"];
// 联合类型

let arr: any[] = ["1", 2, "3", 4, "5", {number: 1}];
// 任意类型

数组泛型

        我们也可以使用数组泛型(Array Generic)来表示数组:

let arr: Array<number> = [1, 2, 3, 4, 5]

用接口表示数组

        接口也可以用来描述数组:

interface IAarray {
    [index: number]: number;
}
let arr: IArray = [1, 2, 3, 4, 5]

        IAarray表示:数组的索引的类型是number,元素的类型也是number。

        虽然接口也可以用来描述数组,但是我们一般不会这样使用,因为这种方式比之前的方式会麻烦很多,不过有一种情况例外,那就是用它来表示类数组。

类数组

        类数组(Array-like Object)不是数组类型,比如arguments

function sum() {
    let args: number[] = arguments;
}

// Type 'IArguments' is missing the following properties from type 'number[]': pop, push, concat, join, and 24 more.
// 'IArguments'类型缺少'number[]'类型的以下属性:pop, push, concat, join等24个。

        上例中,arguments实际上是一个类数组,不能用普通的数组的方式来描述,而应该用接口:

function sum() {
    let args: {
        [index: number]: number;
        length: number;
        callee: Function;
    } = arguments;
}

        在这个例子中,我们除了约束当索引的类型是数字时,值的类型必须是数字之外,也约束了它还有lengthcallee两个属性。

        事实上常用的类数组都有自己的接口定义,如IArgumentsNodeListHTMLCollection等:

function sum() {
    let args: IArguments = arguments;
}

        其中IArguments是TypeScript中定义好了的类型,它实际上就是:

interface IArguments {
    [index: number]: any;
    length: number;
    callee: Function;
}

多维数组

        一个数组的元素可以是另外一个数组,这样就构成了多维数组(Multi-dimensional Array)。

let arr: number[][] = [[1, 2, 3], [1, 2, 3]];

数组在函数中的使用

作为参数传递给函数

let arr: number[] = [1, 2 ,3];
function forEachArr(arr: number[]) {
    arr.forEach(item => {
        console.log(item);
    });
}
forEachArr(arr);

作为函数的返回值

function arrFun(): number[] {
    return [1, 2, 3];
}
let arr: number[] = arrFun();
arr.forEach(item => {
    console.log(item);
});

函数的类型

函数声明

        在 JavaScript 中,有两种常见的定义函数的方式——函数声明(Function Declaration)和函数表达式(Function Expression):

// 函数声明(Function Declaration)
function sum(x, y) {
    return x + y;
}

// 函数表达式(Function Expression)
let mySum = function (x, y) {
    return x + y;
}

        一个函数有输入和输出,要在 TypeScript 中对其进行约束,需要把输入和输出都考虑到,其中函数声明的类型定义较简单:

function sum(x: number, y: number): number {
    return x + y;
}

        注意,输入多余的(或者少于要求的)参数,是不被允许的

function sum(x: number, y: number): number {
    return x + y;
}
sum(1, 2, 3);
// Expected 2 arguments, but got 3.
// 预期有2个参数,但得到了3个。

function sum(x: number, y: number): number {
    return x + y;
}
sum(1);
// Expected 2 arguments, but got 1.
// 预期有2个参数,但得到了1个。

函数表达式

        如果要我们现在写一个对函数表达式(Function Expression)的定义,可能会写成这样:

let mySum = function (x: number, y: number): number {
    return x + y;
};

        这是可以通过编译的,不过事实上,上面的代码只对等号右侧的匿名函数进行了类型定义,而等号左边的mySum,是通过赋值操作进行类型推论而推断出来的。如果需要我们手动给mySum添加类型,则应该是这样:

let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
};

        注意不要混淆了 TypeScript 中的=>和ES6中的=>

        在 TypeScript 的类型定义中,=>用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。

用接口定义函数的形状

        我们也可以使用接口的方式来定义一个函数需要符合的形状:

interface SearchFunc {
    (num1: number, num2: number): boolean;
}

let mySearch: SearchFunc;
mySearch = function(num1: number, num2: number) {
    return num1 - num2 > 0;
}

        采用函数表达式|接口定义函数的方式时,对等号左侧进行类型限制,可以保证以后对函数名赋值时保证参数个数、参数类型、返回值类型不变。

可选参数

        前面提到,输入多余的(或者少于要求的)参数,是不允许的。那么如何定义可选的参数呢?

        与接口中的可选属性类似,我们用?表示可选的参数:

function sum(x: number, y?: number): number {
    if(y) {
        return x + y;
    } else {
        return x;
    }
}
sum(1, 2);
sum(1);

        需要注意的是,可选参数必须接在必需参数后面。换句话说,可选参数后面不允许再出现必需参数了

function sum(y?: number, x: number): number {
    if(y) {
        return x + y;
    } else {
        return x;
    }
}
sum(1, 2);
sum(undefined, 1);
// A required parameter cannot follow an optional parameter.
// 必选参数不能跟在可选参数后面。

参数默认值

        在ES6中,我们允许给函数的参数添加默认值,TypeScript会将添加了默认值的参数识别为可选参数

function sum(x: number, y: number = 2): number {
    if(y) {
        return x + y;
    } else {
        return x;
    }
}
sum(1, 2);
sum(1);

        此时就不受「可选参数必须接在必需参数后面」的限制了:

function sum(y: number = 2, x: number): number {
    if(y) {
        return x + y;
    } else {
        return x;
    }
}
sum(1, 2);
sum(undefined, 1);

剩余参数

        ES6中,可以使用...rest的方式获取函数中的剩余参数(rest 参数),事实上,items是一个数组。所以我们可以用数组的类型来定义它:

function push(array: any[], ...items: any[]) {
    array.push(...items);
}
let arr: any[] = [];
push(arr, 1, 2, 3, 4);

重载

        重载允许一个函数接受不同数量或类型的参数时,作出不同的处理。

        比如,我们需要实现一个函数reverse,输入数字123的时候,输出反转的数字321,输入字符串'hello'的时候,输出反转的字符串'olleh'

        利用联合类型,我们可以这么实现:

function reverse(x: number | string): number | string | void {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

        然而这样有一个缺点,就是不能够精确的表达,输入为数字的时候,输出也应该为数字,输入为字符串的时候,输出也应该为字符串。

        这时,我们可以使用重载定义多个reverse的函数类型:

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string | void {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

        上例中,我们重复定义了多次函数reverse,前几次都是函数定义,最后一次是函数实现。在编辑器的代码提示中,可以正确的看到前两个提示。

        注意,TypeScript会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。

箭头函数

        ES6允许使用箭头=>定义函数,箭头函数提供了一种更加简洁的函数书写方式,箭头函数多用于匿名函数的定义;

let mySum = (x, y) => x + y;

        上面的代码中,并没有对函数进行类型定义,所以还要添加上类型定义。

let mySum = (x: number, y: number): number => x + y;

        上面的代码中,只是对等号右边的匿名函数进行了类型定义,所以还要对等号左边的mySum添加类型。

let mySum: (x: number, y: number) => number = (x: number, y: number): number => x + y;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《stm32自学笔记(第版)pdf》是一本关于STM32单片机的自学教材,提供了丰富的学习资料和实践案例。本书内容全面,涵盖了STM32单片机的基础知识、硬件组成、编程语言和常用外设的详细介绍。 首先,本书首先介绍了STM32单片机的基础知识,包括单片机的工作原理、寄存器的使用方法等。通过对这些基础知识的讲解,读者可以对STM32单片机有一个全面而深入的了解。 其次,本书通过详细的图文实例,介绍了STM32单片机的硬件组成,包括各种外设的连接和使用方法。读者可以通过实践,学习如何使用串口、定时器、中断等外设,进一步提升对STM32单片机的理解和应用能力。 此外,本书还介绍了STM32的编程语言,包括C语言的基础知识和STM32的编程方法。通过对配套开发环境的介绍和实例的编写,读者可以学习如何进行STM32单片机的编程,完成各种常见的功能和应用。 最后,本书提供了大量的实践案例,通过实际的项目,将前面学到的知识进行应用。这些实践案例涵盖了各个领域的应用,包括智能家居、工业控制等。读者可以通过学习这些实践案例,更好地掌握STM32单片机的应用技巧。 综上所述,《stm32自学笔记(第版)pdf》是一本非常实用的STM32单片机自学教材。通过阅读本书并进行实践,读者可以从零基础开始,逐步掌握STM32单片机的各个方面,提高对单片机的理解和应用能力,为以后的实际项目打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值