对 TypeScript
知识点的梳理。
基础类型
布尔值:
boolean
数字:
number
字符串:
string
数组:
any[]
或Array<any>
元组:
[string, number]
枚举:
enum Color {Red, Green, Blue}
从 0 开始,或enum Color {Red = 1, Green, Blue}
从 1 开始Any:
any
Void:
void
类型断言
把一个实体,强行设置为某个类型(告诉编译器这个实例就是这个类型,不用再检查,因为我已经手动检查过了)。
两种形式:
- 尖括号语法
<string>someValue
- as 语法
someValue as string
解构
作用于函数参数:
function f ([first, second]: [number, number]) {
console.log(first);
console.log(second);
}
作用于对象:
let {a, b}: {a: string, b: number} = obj;
接口
对象类型:
interface LabelledValue {
label: string; // 必须包含一个label属性且类型为string
size?: number; // 可选属性
readonly x: number; // 只读属性 变量用const
[propName: string]: any; // 其余未知属性
}
function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}
let myObj = {size: 10, label: "Size 10 Object", x: 1};
printLabel(myObj);
函数类型:
// (参数类型) : 返回类型
interface SearchFunc {
(a: string, b: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
let result = source.search(subString);
return result > -1;
}
可索引的类型:
- 数字索引
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];
- 字符串索引
需要注意,数字索引返回值必须是字符串索引返回值的子类型,因为 js 查找索引会把数字转为字符串再查找。
interface NumberDictionary {
[index: string]: number;
length: number; // 可以,length是number类型
name: string // 错误,`name`的类型与索引类型返回值的类型不匹配
}
类:
只描述了公共部分,不会帮你检查类是否具有某些私有成员。
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
// 另一个例子
interface ClockConstructor {
new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
tick();
}
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
return new ctor(hour, minute);
}
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("beep beep");
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("tick tock");
}
}
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
继承接口:
interface Shape {
color: string;
}
interface Square extends Shape {
sideLength: number;
}
let square = <Square>{};
square.color = "blue";
square.sideLength = 10;
类
public
:
默认为 public
,公共成员,可以自由访问。
private
:
私有,不能在当前类的外部访问。
protected
:
只能在当前类或当前类的子类中访问。
存储器(get
、 set
):
// 设置密码
let passcode = "secret passcode";
class Employee {
private _fullName: string;
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
// 只有密码正确时才有权限修改
if (passcode && passcode == "secret passcode") {
this._fullName = newName;
}
else {
console.log("Error: Unauthorized update of employee!");
}
}
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
alert(employee.fullName);
}
静态属性 static
:
存在于类本身上面而不是类的实例上,调用时 类名.属性名
,而不是 this.属性名
(别的属性叫实例成员,那些仅当类被实例化的时候才会被初始化的属性)。
抽象类 abstract
:
类做为其它派生类的基类使用(多态)。 它们一般不会直接被实例化。
/**
* Animal 作为基类,makeSound 方法必须在派生类中实现
* 当一个函数接受 Animal 类的实例作为参数时,肯定会有 move 和 makeSound 方法(多态)
*/
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log('roaming the earch...');
}
}
函数
let myAdd: (baseValue: number, increment: number) => number = // 定义类型
function(x: number, y: number): number { return x + y; }; // 函数
// 或者在函数块省略类型,会自动识别
let myAdd: (baseValue: number, increment: number) => number =
function(x, y) { return x + y; };
可选参数 :
TypeScript 中函数的参数数量,必须与定义类型时的参数数量一致,不能多不能少。
// 当参数是可选的时候,用 ?,且必须为最后参数
function buildName(firstName: string, lastName?: string):void {}
默认参数 :
function buildName(firstName: string, lastName = "Smith"):void {}
剩余参数 :
可以把所有参数收集到一个变量里。
function buildName(firstName: string, ...restOfName: string[]):void {}
重载 :
根据不同类型的参数,返回不同类型的值。
function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): any { // 这个类型检查并不是重载的一部分
// Check to see if we're working with an object/array
// if so, they gave us the deck and we'll pick the card
if (typeof x == "object") {
let pickedCard = Math.floor(Math.random() * x.length);
return pickedCard;
}
// Otherwise just let them pick the card
else if (typeof x == "number") {
let pickedSuit = Math.floor(x / 13);
return { suit: suits[pickedSuit], card: x % 13 };
}
}
泛型
类型变量
// 表示返回值的类型与传入参数的类型是相同的
// T帮助我们捕获用户传入的类型(比如:number)
function identity<T>(arg: T): T {
return arg;
}
// 使用方法一
let output = identity<string>("myString");
// 使用方法二 编译器会根据传入的参数自动地帮助我们确定T的类型
let output = identity("myString");
用接口表示
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
// 或者
interface GenericIdentityFn {
<T>(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn = identity;
泛型类 :
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; };
泛型约束 :
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}