我是靠谱客的博主 缓慢跳跳糖,这篇文章主要介绍TypeScript语法规范,现在分享给大家,希望可以做个参考。

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
6
let 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
3
let fib:number[] = [1,2,3] // let fib1:number[] = [1,2,3,'1'] // 不能将类型“string”分配给类型“number”

5.2 数组泛型

复制代码
1
2
let fibonacci: Array<number> = [1, 1, 2, 3, 5];

5.3 接口表示

复制代码
1
2
3
4
5
interface 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
4
function 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
29
interface 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
15
declare 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
2
declare var $: (selector: string) => any;

2. 全局函数

复制代码
1
2
declare function jQuery(selector: string): any;

3. 声明全局类

复制代码
1
2
3
4
5
6
declare class Animal { name: string; constructor(name: string); sayHi(): string; }

4. 枚举

复制代码
1
2
3
4
5
6
7
declare 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
6
type EventNames = 'click' | 'scroll' | 'mousemove'; // 参数event的值必须为上面三个其中一个 function handleEvent(e: Element, event: EventNames){ // do something }

3. 元组

复制代码
1
2
3
let om: [string, number]; om[0] = 'Tom';

4. 枚举

4.1 普通枚举

复制代码
1
2
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};

4.2 常数枚举

常数枚举与普通枚举的区别是,它会在编译阶段被删除,并且不能包含计算成员

复制代码
1
2
3
4
const enum Directives { Up, Down, Left, Right }

4.3 外部枚举

常出现在声明文件中

复制代码
1
2
3
4
declare 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
7
class 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
2
interface B extends interfaceA {}

3. 接口继承类

复制代码
1
2
interface 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
9
class 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
4
function con<T = string>(arg: T): T{ return arg }

最后

以上就是缓慢跳跳糖最近收集整理的关于TypeScript语法规范的全部内容,更多相关TypeScript语法规范内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(64)

评论列表共有 0 条评论

立即
投稿
返回
顶部