9. TypeScript—函数
用function
来定义函数
function sum(x, y) { return x + y; }
函数重载
重载是方法名字相同,而参数不同,返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
//参数类型不同: function disp(string):void; function disp(number):void; //参数数量不同: function disp(n1:number):void; function disp(x:number,y:number):void; //参数类型顺序不同: function disp(n1:number,s1:string):void; function disp(s:string,n:number):void;
然后,好像也没啥补充点了,其他的大部分也都不常用,就不写进来了。只要记住,JS能用的语法,TS都能用。
10. TypeScript—类型推论和类型断言
如果没有明确的指定类型,那么 TypeScript 会依照类型推论的规则推断出一个类型。
类型推论
以下代码虽然没有指定类型,但是会在编译的时候报错:
let myFavoriteNumber = 'seven'; myFavoriteNumber = 7; //事实上等价于 let myFavoriteNumber: string = 'seven'; myFavoriteNumber = 7;
11. TypeScript—枚举
枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等。
枚举使用 enum
关键字来定义:
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat}; console.log(Days["Sun"]); // 0 console.log(Days[0]); // Sun
我们也可以给枚举项手动赋值,未手动赋值的枚举项会接着上一个枚举项递增:
enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat}; console.log(Days["Sun"]); // 7 console.log(Days["Mon"]); // 1 console.log(Days["Tue"]); // 2 console.log(Days["Sat"]); // 6
当然,手动赋值的枚举项也可以为小数或负数,此时后续未手动赋值的项的递增步长仍为 1:
enum Days {Sun = -7, Mon = 1.5, Tue, Wed, Thu, Fri, Sat}; console.log(Days["Tue"]); // 2 console.log(Days["Mon"]); // 1.5
其他细节就不写了,用到再说。
12. TypeScript—泛型
泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
//首先,我们来实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值: function createArray(length: number, value: any): Array<any> { let result = []; for (let i = 0; i < length; i++) { result[i] = value; } return result; } createArray(3, 'x'); // ['x', 'x', 'x']
上例中,我们使用了之前提到过的数组泛型来定义返回值的类型。
这段代码编译不会报错,但是一个显而易见的缺陷是,它并没有准确的定义返回值的类型。Array 允许数组的每一项都为任意类型。但是我们预期的是,数组中每一项都应该是输入的 value 的类型。这时候,泛型就派上用场了:
function createArray<T>(length: number, value: T): Array<T> { let result: T[] = []; for (let i = 0; i < length; i++) { result[i] = value; } return result; } createArray<string>(3, 'x'); // ['x', 'x', 'x']
多个类型参数的泛型:
//定义了一个 swap 函数,用来交换输入的元组。 function swap<T, U>(tuple: [T, U]): [U, T] { return [tuple[1], tuple[0]]; } swap([7, 'seven']); // ['seven', 7]
13. TypeScript—字符串字面量类型
字符串字面量类型用来约束取值只能是某几个字符串中的一个。字符串字面量类型使用 type
进行定义,下面举一个简单的例子:
//使用 type 定了一个字符串字面量类型 EventNames,它只能取三种字符串中的一种。 type EventNames = 'click' | 'scroll' | 'mousemove'; function handleEvent(ele: Element, event: EventNames) { console.log(EventNames) } // 没问题 handleEvent('scroll'); // 报错,event 不能为 'focus' handleEvent('focus');
14. TypeScript—命名空间
命名空间是为了避免变量命名冲突,TypeScript 官方将命名空间视为“内部模块”。
如果声明相同名称的命名空间,TypeScript 编译器会将其合并为一个声明。
使用 namespace 关键字来声明命名空间。TypeScript 的命名空间可以将代码包裹起来,只对外暴露这个命名空间对象,通过 export 关键字将命名空间内的变量挂载到命名空间对象上。命名空间本质上就是一个对象,将其内部的变量组织到这个对象的属性上:
namespace Calculator { const fn = (x: number, y: number) => x * y export const add = (x: number, y:number) => x + y }
其编译后的结果
"use strict"; var Calculator; (function (Calculator) { var fn = function (x, y) { return x * y; }; Calculator.add = function (x, y) { return x + y; }; })(Calculator || (Calculator = {}));
那么,我们就可以访问 Calculator 对象上的 add 属性了:
Calculator.add(2, 3)
15. TypeScript—类型声明文件
假如我们想使用第三方库 jQuery,一种常见的方式是在 html 中通过<script> 标签引入 jQuery,然后就可以使用全局变量 $或 jQuery了。但是在 ts 中,编译器并不知道 $或 jQuery是什么东西。
声明文件
当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。通常我们会把声明语句放到一个单独的文件(如jQuery.d.ts)中,这就是声明文件,声明文件必需以 .d.ts 为后缀。
一般来说,ts 会解析项目中所有的 *.ts 文件,当然也包含以 .d.ts 结尾的文件。所以当我们将 jQuery.d.ts 放到项目中时,其他所有 *.ts 文件就都可以获得 jQuery 的类型定义了。
第三方声明文件
当然,jQuery 的声明文件不需要我们定义了,JQuery已经帮我们定义好了。
我们可以直接下载下来使用,但是更推荐的是使用 @types 统一管理第三方库的声明文件。
@types 的使用方式很简单,直接用 npm 安装对应的声明模块即可,以 jQuery 举例:
npm install @types/jquery --save-dev