命令
生成 tsconfig.json 文件
tsc --init联合类型
使用
|分隔类型
let nameOrAge: string | number = "gauhar";
nameOrAge = 18;合并类型
使用
&符号,将多个类型合并
const name: { firstName: string } & { lastName: string } = {
firstName: "gauhar",
lastName: "chan",
};interface 接口
名称使用大写开头,或者以
I开头使用
?说明属性是可选的。
[propName: string]: any指定该接口有,这个any说明任意属性可以是任意类型。如果换成string,则该接口下,必选、可选的属性都必须是string类型。
readonly定义属性只读。即初始化赋值,后面不可改。
interface Person {
name: string;
age?: number;
[propName: string]: any;
readonly noChange: string;
}
let tom: Person = {
name: "Tom",
};数组
number[]: 数字类型数组
string[]: 字符串数组
any[]: 任意类型数组
函数
可选参数
c?: number,非可选参数缺一不可,类型也要一致
但,如果参数使用默认值,参数就是可选参数,那么限制就不存在了
let add = (a: number = 123, b: number, c?: number): number => a + b;上面的写法,add 的类型并没有指定,而是推导出来的。下面是指定的写法
左边定义 add 的
=>并不是es6中的箭头函数,而是说明是函数,返回number类型
let add: (a: number, b: number, c?: number) => number = (
a: number,
b: number,
c?: number
): number => a + b;
// 上面的写法不美观,可以使用接口代替
interface Iadd {
(a: number, b: number, c?: number): number;
}
let add: Iadd = (a: number, b: number, c?: number): number => a + b;剩余参数
...items就是除了array的所有参数,而他是一个数组,所以使用数组类型声明。他必须放在参数最后一位
function push(array: any[], ...items: any[]) {
items.forEach(function (item) {
array.push(item);
});
}
let a = [];
push(a, 1, 2, 3);重载
重载允许一个函数接受不同数量或类型的参数时,作出不同的处理。
多次定义不同类型的函数,这样就可以保证当参数
a是number类型的时候返回number类型
TypeScript 会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。
function f1(a: number): number;
function f1(a: string): string;
function f1(a: number | string): number | string {
return typeof a === "number" ? 1 : "1";
}类型断言
我们自己指定一个值的类型。
需要注意的是,类型断言只能够「欺骗」TypeScript 编译器,无法避免运行时的错误,反而滥用类型断言可能会导致运行时错误
let duan: string | number;
(duan as string) = 123; // 报错,类型断言为string类型当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型中共有的属性或方法
interface Icat {
name: string;
run(): void;
}
interface Ifish {
name: string;
swim(): void;
}
function isCat(animal: Icat | Ifish) {
console.log(animal.name); // 共同拥有name属性
console.log(animal.run); // 报错 run只存在于Icat接口,并不是共同拥有的
}使用断言,指定为特定的接口,就可以使用
function ifFish(animal: Icat | Ifish) {
(animal as Icat).run();
}声明文件
.d.ts 文件
全局声明
全局变量的声明文件主要有以下几种语法:
declare var声明全局变量declare function声明全局方法declare class声明全局类declare enum声明全局枚举类型declare namespace声明(含有子属性的)全局对象interface和type声明全局类型
内置对象
eq:
IArguments描述arguments这个类数组常用的类数组都有自己的接口定义,如
IArguments,NodeList,HTMLCollection等
let b: Boolean = new Boolean(1);
let e: Error = new Error("Error occurred");
let d: Date = new Date();
let r: RegExp = /[a-z]/;类型别名
给类型起一个别的名称,下面
$1代表number类型。使用type定义。建议名称首字母大写
type $1 = number;
type St = string;
const a: $1 = 123;字符串字面量类型
约束只能取指定的值
type name = "gauhar" | "chan";
let name2: name = "chan";元组
初始化赋值时(或者是通过下标赋值),必须按照顺序的类型
let tuple: [string, number] = ["string", 123];越界的元素
使用
push等方法时,元素的类型会被限制为元组中每个类型的联合类型
let tuple: [string, number];
tuple.push(123);
tuple.push(true); // 报错。 类型“true”的参数不能赋给类型“string | number”的参数。枚举
定义枚举的时候就要初始化赋值,如果没有指定值,则默认以 0 开始赋值,
0,1,2...。不能通过属性名修改值 。
enum Week {
SUN,
MON,
TUE = ‘星期二’
}
Week.SUN = 'dsf' // 报错,只读属性
console.log(Week.SUN === 0); // true未手动赋值的枚举项会接着上一个枚举项递增,下面的TUE就是 2、接着 3、4 以此类推
enum Week {
SUN = 5,
MON = 1,
TUE, // 2
}类
静态方法
使用 static 修饰符修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用:
class Animal {
static isAnimal(a) {
return a instanceof Animal;
}
}
let a = new Animal("Jack");
Animal.isAnimal(a); // true
a.isAnimal(a); // TypeError: a.isAnimal is not a functionES7
实例属性
不需要通过
this.xxx来定义
class Animal {
name = "Jack";
constructor() {
// ...
}
}
let a = new Animal();
console.log(a.name); // Jack修饰符
public修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是public的private修饰的属性或方法是私有的,不能在声明它的类的外部访问protected修饰的属性或方法是受保护的,它和private类似,区别是它在子类中也是允许被访问的
readonly 属性
只读,不可修改
装饰器
方法装饰器
let test = (value?: any) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
const method = descriptor.value
descriptor.value = (...args: any[]) => {
console.log(value);
if (value) method.apply(this, args)
}
return descriptor
}
@test('hello test')
public mounted (): void {
console.log('mounted');
}