元组
数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象
// 数组
let arr:number[] = [1,2]
// 元组
let arr1:[string,number]=['1',2]
// 但是使用联合类型/类型别名 同样可以实现元组的效果
// 区别是元组对每一项进行类型约束 而下面实现的只要满足类型就可以
type name = string | number
// 进行类型使用
let arr2: name[] = ['1','2', 1]
对元组增加新的元素时,它的类型会被限制为元组中每个类型的联合类型
let tom: [string, number]
tom = ['str', 20]
tom.push('str1')
tom.push(11)
// tom.push(true)
// Argument of type 'true' is not assignable to parameter of type 'string | number'.
枚举
枚举用了C#的思想,常常用于取值被限定在一定范围内的场景,比如:颜色(红绿蓝),方向(上下左右),时间(年月日),旋转角度(0,90,180)。
使用关键字enum
来进行定义
enum Direction {Up,Down,Left,Right,
}
// 编译js之后
var Direction;
(function (Direction) {Direction[Direction["Up"] = 0] = "Up";Direction[Direction["Down"] = 1] = "Down";Direction[Direction["Left"] = 2] = "Left";Direction[Direction["Right"] = 3] = "Right";
})(Direction || (Direction = {}));
编译之后的代码这样,我们可以这样调用,没有手动赋值是从0开始递增的
console.log(Direction["Up"] === 0); // true
console.log(Direction[0] === "Up"); // true
可以对枚举项进行手动赋值,未手动赋值的枚举项会接着上一个枚举项递增
enum Direction {Up=2, Down,Left,Right}
console.log(Direction["Up"] === 2) // true
console.log(Direction["Down"] === 3) // true
console.log(Direction["Left"] === 4) // true
未手动赋值的枚举项会接着上一个枚举项递增,就会出现下面这种情况
enum Direction {Up=2, Down=1,Left,Right}
console.log(Direction["Up"] === 2); // true
console.log(Direction["Left"] === 2); // true
console.log(Direction[2] === "Up"); // false
console.log(Direction[2] === "Left"); // true
// 所以使用的时候需要注意,最好不要出现这种覆盖的情况
// 导致这一原因 是编译的时候 后面的值会将前面的覆盖
使用 const enum
定义的枚举类型为常数枚举
const enum Directions {Up,Down,Left,Right
}let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]
编译后的结果
var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
正常项目使用的时候,模块化(在声明的d.ts文件导出使用),在项目文件中直接定义使用
// 推荐第一种模块化
// xxx.d.ts
// 以方向问例,正常根据自己需要定义
// 导出
export enum Directions {Up,Down,Left,Right
}
// xxx.vue
// 引入
import { Directions } from 'xxx.d.ts'
// 使用
Directions.Up
Down.Down
TypeScript 中类的用法
TypeScript 可以使用三种访问修饰符,分别是 public
、private
和 protected
。
-
public
修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是public
的 -
private
修饰的属性或方法是私有的,不能在声明它的类的外部访问 -
protected
修饰的属性或方法是受保护的,它和private
类似,区别是它在子类中也是允许被访问的
示例:
public
class Obj {public namepublic constructor(name) {this.name = name}
}
let a = new Obj('zyk')
console.log(a.name) // zyk
// public修饰的属性可以进行更改
a.name = 'ly'
console.log(a.name) // ly
private
class Obj {private namepublic constructor(name) {this.name = name}
}
let a = new Obj('zyk')
console.log(a.name) // zyk
// private修饰的属性不可以进行更改,会报错
a.name = 'ly'// private 修饰的属性或方法,在子类中也是不允许访问的,下面会报错
class Cat extends Obj {constructor(name) {super(name)console.log(this.name)}
}
protected
class Obj {protected namepublic constructor(name) {this.name = name}
}// protected修饰的属性或方法,允许在子类中访问
class Cat extends Obj {constructor(name) {super(name)console.log(this.name)}
}
类的类型
给类加上 TypeScript 的类型很简单,与接口类似:
class Media {name: string;constructor(name: string) {this.name = name;}sayHi(): string {return `My name is ${this.name}`;}
}let a: Media = new Media('zyk');
console.log(a.sayHi()); // My name is zyk
泛型
书写一个函数这个函数会返回任何传入它的值
不适用泛型我们定义函数是
function callBack(a: any): any {return a
}
使用any
能解决这个,但是我们就失去了传入的类型和传出的类型应该是一致的。比如:传入了字符串,我们只知道任何类型的值都能返回
因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。
我们使用了类型变量T
,它是一种特殊的变量,只用于表示类型而不是值
function callBack<T>(a: T): T {return a
}
添加了类型变量T
,我们就可以使用这个类型捕获传入的类型,之后再次使用T
当做返回值类型。我们把这个函数称之为泛型
定义泛型函数后,有两种使用方法
// 第一种是,传入所有的参数,包含类型参数:let output = callBack<string>("myString")// 第二种方法更普遍,利用类型推论,推导出T的类型let output = callBack("myString")
使用泛型变量
如果我们想打印入参的某一个属性(length)
function callBack<T>(a: T): T {console.log(a.length); // Error: T doesn't have .lengthreturn a
}
// 引入传入的T为any类型,但是对于一些类型number是没有length属性,这会出现错误
这个时候可以通过操作T
类型的数组而不直接操作T
,对于每一类型的数组有两种定义:类型[]、Array<类型>
我们就可以这样书写
function callBack <T>(a:Array<T>):Array<T> {console.log(a.length)return a
}
function callBack <T>(a:T[]):T[] {console.log(a.length)return a
}