TypeScript是JavaScript的超集,提供了更严格的类型声明,方便在静态类型检查时就避免因为类型问题产生的bug。
工欲善其事,必先利其器,让我们来看看TypeScript是怎样声明数据类型的
一. 声明
1. 基本数据类型+ts特有类型void声明
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14/** * Note: 未指定类型时, TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型 * 如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查 * let a = 7 * a = 'seven' // Error:不能将类型“"seven"”分配给类型“number” */ const num:number = 123 const str:string = '123' const bool:boolean = true const und:undefined = undefined const nu: null = null let u: void; console.log(num,str,bool,und,nu, u) // 123 '123' true undefined null undefined
2. 任意值类型
复制代码
1
2
3
4
5
6let everyOne: any = 'seven'; console.log(everyOne) everyOne = 7 console.log(everyOne) console.log(everyOne.name)
3. 联合类型,表示取值可以为多种类型中的一种
复制代码
1
2
3// 用|表示联合 let test: string | number;
4. 对象类型-接口
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29/** * Note: 定义的变量不允许比接口属性少或多,形状必须和接口一致 * 如果希望不完全匹配,可使用可选属性(该属性可以不存在,但仍不允许添加) * interface Person { * name: string; * age?: number; * } * * 要添加的话使用任意属性 * interface Person { * name: string; * age?: nuber; * [propName: string]: any; * } * */ interface Person { readonly id: number; // 只读属性 name: string; age?: number; // 可选属性 [propName: string]: any; // 任意属性 } t let tom: Person = { id: 123, name: 'TOM', age: 25, gender: '女' }
5. 数组类型
5.1 数组+方括号表示法
复制代码
1
2
3let fib:number[] = [1,2,3] // let fib1:number[] = [1,2,3,'1'] // 不能将类型“string”分配给类型“number”
5.2 数组泛型
复制代码
1
2let fibonacci: Array<number> = [1, 1, 2, 3, 5];
5.3 接口表示
复制代码
1
2
3
4
5interface NumberArray { [index: number]: number; } let fib1: NumberArray = [1,2,3]
6. 类数组
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/** * Note: * 类数组不是数组类型,如arguments,dom queryselector * 通常用接口表示,可以自定义接口,也可用TypeScript封装的接口 */ interface IArguments { [index: number]: any; length: number; callee: Function; } function sum() { let args: IArguments = arguments console.log(args) } let liList: HTMLCollection = document.getElementsByTagName('li')
7. 函数声明
7.1 函数对输入输出类型进行约束
复制代码
1
2
3
4function sum2(x: number, y: number): number { return x + y; }
7.2 函数表达式
复制代码
1
2
3
4
5
6
7
8
9/** * Note: * 下面表达式等号右边的为函数声明, 左边的是对mySum变量的约束 * 左边的=>与es6中的箭头函数意义不同,代表的是函数类型,箭头左边为输入类型,右边为输出类型 */ let mySum: (x: number, y: number) => number = function (x: number, y: number): number { return x + y; };
7.3 接口定义函数
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29interface SearchFunc { (source: string, subString: string): boolean; } let mySearch: SearchFunc; mySearch = function(source: string, subString: string) { return source.search(subString) !== -1; } // 可选参数, 可选参数后面不允许再出现必需参数,可以跟默认参数 function buildName(name?: string, age: number = 0){ return name + age } // 剩余参数, rest参数只能是最后一个参数 function push(array, ...items: any[]){ items.forEach(function(item){ array.push(item); }) } // 函数重载,当函数体中有分支时,可能返回不同类型的值,可以使用重载 function reverse(x: number): number; function reverse(x: string): string; function reverse(x: number | string): number | string { if (typeof x === 'number') { return Number(x.toString().split('').reverse().join('')); } else if (typeof x === 'string') { return x.split('').reverse().join(''); } }
二. 声明文件
当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能
声明文件必需以 .d.ts 为后缀
声明文件中下面命令代表含义:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15declare var 声明全局变量 declare function 声明全局方法 declare class 声明全局类 declare enum 声明全局枚举类型 declare namespace 声明(含有子属性的)全局对象 interface 和 type 声明全局类型 export 导出变量 export namespace 导出(含有子属性的)对象 export default ES6 默认导出 export = commonjs 导出模块 export as namespace UMD 库声明全局变量 declare global 扩展全局变量 declare module 扩展模块 /// <reference /> 三斜线指令
1. 全局变量
复制代码
1
2declare var $: (selector: string) => any;
2. 全局函数
复制代码
1
2declare function jQuery(selector: string): any;
3. 声明全局类
复制代码
1
2
3
4
5
6declare class Animal { name: string; constructor(name: string); sayHi(): string; }
4. 枚举
复制代码
1
2
3
4
5
6
7declare enum Directions { Up, Down, Left, Right }
5. 声明合并
复制代码
1
2
3
4
5
6// jQuery即是一个函数,又是一个对象,有自己的属性 declare function jQuery(selector: string): any; declare namespace jQuery { function ajax(url: string, settings?: any): void; }
三. 进阶声明
类型别名与字符串字面量类型都是使用 type 进行定义
1. 类型别名
复制代码
1
2
3
4
5
6
7
8// 为string起个类型别名Name type Name = string; type NameResolver = () => string; type NameOrResolver = Name | NameResolver; // 声明时可用Name代表string类型 let name1: Name = '123' console.log(name1) // 123
2. 字符串字面量
复制代码
1
2
3
4
5
6type EventNames = 'click' | 'scroll' | 'mousemove'; // 参数event的值必须为上面三个其中一个 function handleEvent(e: Element, event: EventNames){ // do something }
3. 元组
复制代码
1
2
3let om: [string, number]; om[0] = 'Tom';
4. 枚举
4.1 普通枚举
复制代码
1
2enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
4.2 常数枚举
常数枚举与普通枚举的区别是,它会在编译阶段被删除,并且不能包含计算成员
复制代码
1
2
3
4const enum Directives { Up, Down, Left, Right }
4.3 外部枚举
常出现在声明文件中
复制代码
1
2
3
4declare enum Directions { Up, Down, Left, Right }
四. 类
1. TypeScirpt中类的用法
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23/** * Note: * public、private、protected(受保护的) * 1. 使用private修饰的属性或方法,在子类也不允许访问 * 2. 使用protected修饰,在子类中允许访问 * 3. 当构造函数修饰为 private 时,该类不允许被继承或者实例化 * 4. 当构造函数修饰为 protected 时,该类只允许被继承 */ class Animal { protected name; public constructor(name) { this.name = name; } } class Cat extends Animal { constructor(name) { super(name); console.log(this.name); } }
2. 只读属性
readonly,只读属性关键字,只允许出现在属性声明或索引签名中
注意如果 readonly 和其他访问修饰符同时存在的话,需要写在其后面
复制代码
1
2
3
4
5
6
7class Animal2 { // public readonly name; public constructor(public readonly name) { this.name = name; } }
3. 抽象类
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21/** * Note: abstract 用于定义抽象类和其中的抽象方法 * 抽象类不允许被实例化 * 抽象类中的抽象方法必须被子类实现 */ abstract class Animal3 { public name; public constructor(name) { this.name = name; } public abstract sayHi(); } class Cat1 extends Animal3 { public sayHi() { console.log(`Meow, My name is ${this.name}`); } } let cat = new Cat1('Tom');
五. 类与接口
1. 实现(implements)
可以将不同类之间共有的特性提取成接口(interface),用implements关键字实现
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13// 报警器接口 interface Alarm { alert(); } class Door { } // 安全门继承门的类 并实现报警器 class SecurityDoor extends Door implements Alarm { alert() { console.log('SecurityDoor alert'); } }
2. 接口可以继承接口
复制代码
1
2interface B extends interfaceA {}
3. 接口继承类
复制代码
1
2interface B extends classA {}
六. 泛型
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
1. 单个类型参数
复制代码
1
2
3
4
5
6
7
8
9
10
11// 使用T指代任意输入的类型, 输出则为Array<T> 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']
2. 多个类型参数
复制代码
1
2
3
4
5
6// 定义泛型的时候,可以一次定义多个类型参数 function swap<A, S>(tuple: [A, S]): [S, A] { return [tuple[1], tuple[0]]; } console.log(swap([7, 'seven']));
3. 泛型约束
复制代码
1
2
3
4
5
6
7
8
9// 比如让一个函数的参数和返回值必须拥有length方法时 interface Len { length: number; } function lenFunc<T extends Len>(arg: T): T { console.log(arg.length); return arg }
4. 使用泛型接口
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 使用含有泛型的接口来定义函数的形状 interface CreateArrayFunc { <T>(length: number, value: T): Array<T>; } let createArray2: CreateArrayFunc; createArray2 = function<T>(length: number, value: T): Array<T> { let result: T[] = []; for (let i = 0; i < length; i++) { result[i] = value; } return result; } createArray2(3, 'x');
5. 泛型类
复制代码
1
2
3
4
5
6
7
8
9class GenericNumber<T> { zeroValue: T; add: (x: T, y: T) => T; } let myGenericNumber = new GenericNumber<number>(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function(x, y) { return x + y; };
6. 为泛型指定默认类型
复制代码
1
2
3
4function con<T = string>(arg: T): T{ return arg }
最后
以上就是缓慢跳跳糖最近收集整理的关于TypeScript语法规范的全部内容,更多相关TypeScript语法规范内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复