跳到主要内容

基础

数据类型

原始数据类型

// 布尔值
const isDone: boolean = false;
// 数值
const num: number = 1;
// 字符串
const myName: string = "Tom";
// 表示函数返回空
const alertName = (): void => {
console.log("My name is Tom");
};
// undefined 和 null 是任何类型的子类型
// undefined 表示变量没有值得初始状态;
const u: undefined = undefined;
let num: number = undefined;
// 表示什么都没有
const n: null = null;

其他类型

any
// 表示可以赋予任何类型, 可以使用任何类型的属性和方法
let anyThing: any = "Tom";
unknown
// 表示不知道类型的变量
// 要求我们使用类型断言确定类型
const n: unknown = 1;
never
// never 是任何值的子类型
// never 表示永远不存在值的类型
// 函数不会返回值, 抛出异常时, 返回 never
function infiniteLoop(): never {
while (true) {}
}
void
// 表示没有任何类型
function warnUser(): void {
console.log("This is my warning message");
}

接口

定义接口
interface Person {
name: string;
age: number;
}
可选属性
interface Person {
name: string;
age?: number;
}
任意属性
// 确定任意属性后, 确定属性和可选属性必须为任意属性的子类型
interface Person {
name: string;
age?: number;
[propName: string]: string | number;
}
只读属性
interface Person {
readonly id: number;
name: string;
age?: number;
[propName: string]: any;
}
接口继承接口
interface Alarm {
console.log(): void;
}
interface LightableAlarm extends Alarm {
lightOn(): void;
lightOff(): void;
}

函数类型

语法格式
function (x: number, y: number): number {
return x + y;
};
const sum = (x: number, y: number): number => {
return x + y;
};
可选类型
// 可选参数位于必选参数后
const buildName = (firstName: string, lastName?: string) => {
// ...
};
函数默认值
const buildName = (firstName: string, lastName: string = "kong") => {
// ...
};
任意数量参数
// 必须位于最后
const push = (array: any[], ...items: any[]) => {
//...
};
函数重载
// 一个函数接受不同数量或类型的参数
// 进行不同的处理
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string | void {
if (typeof x === "number") {
return Number(x.toString().split("").reverse().join(""));
} else if (typeof x === "string") {
return x.split("").reverse().join("");
}
}
实现箭头函数重载
  • 使用 interface 和 as 实现箭头函数重载;
interface FN {
(x: number): number;
(x: number, y: number): number;
}
const reverse1: FN = (x: number, y?: number): number => {
if (y) {
return x + y;
} else {
return x;
}
};
const reverse2 = ((x: number, y?: number): number => {
if (y) {
return x + y;
} else {
return x;
}
}) as FN;

联合类型和交叉类型

联合类型
  • 联合类型表示几个类型中的一个;
  • 只能访问联合类型共有的方法和属性;
let myFavoriteNumber: string | number;
myFavoriteNumber = "seven";
myFavoriteNumber = 7;
交叉类型
  • 交叉类型将多个类型合并在一起;
  • 具有多个类型的属性和方法;
interface ErrorHandling {
success: boolean;
error?: { message: string };
}

interface ArtworksData {
artworks: { title: string }[];
}
type ArtworksResponse = ArtworksData & ErrorHandling;

字面量类型

// 约束取值只能为规定值中的一个;
type EventNames = "click" | "scroll" | "mousemove";
const handleEvent = (ele: Element, event: EventNames) => {
// do something
};
handleEvent(document.getElementById("hello"), "scroll"); // 没问题
handleEvent(document.getElementById("world"), "dblclick"); // 报错, event 不能为 'dblclick'

数组类型

// 类型 + 方括号
let fibonacci: number[] = [1, 1, 2, 3, 5];
let fibonacci: object[] = [1, 1, 2, 3, 5];
// 泛型
let fibonacci: Array<number> = [1, 1, 2, 3, 5];
// 接口
interface NumberArray {
[index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];

元组

语法格式
// 元组各项类型不同且固定
// 初始化元组需要赋值所有项
const tom: [string, number] = ["Tom", 25];
越界元素
  • 类型限制为元组中各类型的联合类型;

枚举

语法格式
// enum 用于取值限制在一定范围内的场景
// enum 成员赋值为从 0 递增的数字, 枚举值和枚举名相互映射
enum Directions {
Up,
Down,
Left,
Right,
}

Directions[0] = "Up";
Directions["Up"] = 0;
手动赋值
// 未手动赋值的根据上一个枚举项递增
// 该例中 Up 和 Left 均为 3, 但 ts 并不报错, 最好不要出现该情况
enum Directions {
Up = 3,
Down = 2,
Left,
Right,
}

类型断言

语法格式
// 推荐使用 as
const tom = getCacheData("tom") as Cat;
const tom = <Cat>getCacheData("tom");
使用场景
  • 明确联合类型中的一个类型;
  • 将任何类型断言为 any;
  • 将 any 断言成具体类型;
双重断言
// 使用双重断言可以将任意类型断言为另一任意类型
// 建议不要使用
A as any as B;

基本概念

访问修饰符
// public 公有, 任何地方均可访问
// private 私有, 仅能从声明类内部访问
// protected 保护, 仅能从声明类极其子类内部访问
class Animal {
private name;
public constructor(name) {
this.name = name;
}
}
readonly
// 只读修饰符
// 与其他访问修饰符共存时, 放在其后
class Animal {
// public readonly name;
public constructor(public readonly name) {
// this.name = name;
}
}
abstract
// 定义抽象类及其抽象方法
// 抽象类和方法不能被实例化
abstract class Animal {
public name;
public constructor(name) {
this.name = name;
}
public abstract sayHi();
}
使用类
class Animal {
// ...
}
let a: Animal = new Animal("Jack");

类和接口

类实现接口
interface Alarm {
console.log(): void;
}
interface Light {
lightOn(): void;
lightOff(): void;
}
class Car implements Alarm, Light {
console.log() {
console.log("Car alert");
}
lightOn() {
console.log("Car light on");
}
lightOff() {
console.log("Car light off");
}
}
类继承接口
// 声明类的同时声明了一个同名类型
// 创建的同名类型中只包含类的实例属性和方法
class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
interface Point3d extends Point {
z: number;
}
let point3d: Point3d = { x: 1, y: 2, z: 3 };

泛型

基本概念

泛型
  • 定义函数,接口或类时;
  • 不确定具体类型;
  • 在使用时确定;
语法格式
// 定义泛型
// 普通函数
function createArray<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
// 箭头函数
const 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']
多个类型参数
const swap = <T, U>(tuple: [T, U]): [U, T] => {
return [tuple[1], tuple[0]];
};
泛型参数的默认类型
// 没有指定类型且 ts 也无法推断类型时, 使用默认类型
const createArray = <T = string>(length: number, value: T): Array<T> => {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
};

泛型约束

  • 函数内部使用泛型时,
  • 由于不清楚其类型;
  • 无法使用类型的属性和方法;
  • 使用泛型约束指定其包含的属性和方法;
interface Lengthwise {
length: number;
}
const loggingIdentity = <T extends Lengthwise>(arg: T): T => {
console.log(arg.length);
return arg;
};

泛型接口

// 通过定义泛型接口定义函数形状
interface CreateArrayFunc {
<T>(length: number, value: T): Array<T>;
}

const createArray: CreateArrayFunc = <T>(
length: number,
value: T
): Array<T> => {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
};

泛型类

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;
};

高级类型

类型推断

基础
  • 在未指明类型的情况下;
  • 根据规则判断变量类型;
基本类型推断
  • 根据表达式右侧的值推断左侧变量类型;
    • 赋值操作;
      • 初始化变量;
      • 默认参数值;
    • 函数 return 返回类型;
最佳通用类型推断
  • 常用于数组类型推断;
  • 根据最佳通用类型算法;
  • 选择与所有数组子项类型兼容的数组类型;
上下文类型推断
  • 常用于事件处理中对 e 的判断;
  • 根据使用变量的位置判断其类型;

类型守卫

使用场景
interface Bird {
fly();
layEggs();
}

interface Fish {
swim();
layEggs();
}

function getSmallPet(): Fish | Bird {
// ...
}

let pet = getSmallPet();
pet.layEggs(); // okay
// 无法判断 pet 是 Bird 或者 Fish, 故不能使用 swim() 方法
pet.swim(); // errors
类型判定
  • parameter is type;
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}

if (isFish(pet)) {
pet.swim();
} else {
pet.fly();
}
使用 in 操作符
  • in 操作符判断类型是否具有某属性;
function move(pet: Fish | Bird) {
if ("swim" in pet) {
return pet.swim();
}
return pet.fly();
}
typeof
  • ts 自动把 typeof 作为类型守卫;
function padLeft(value: string, padding: string | number) {
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
if (typeof padding === "string") {
return padding + value;
}
throw new Error(`Expected string or number, got '${padding}'.`);
}
instanceof
  • ts 自动把 instanceof 作为类型守卫;
// 类型为SpaceRepeatingPadder | StringPadder
let padder: Padder = getRandomPadder();

if (padder instanceof SpaceRepeatingPadder) {
padder; // 类型细化为'SpaceRepeatingPadder'
}
if (padder instanceof StringPadder) {
padder; // 类型细化为'StringPadder'
}

索引类型

keyof
  • keyof T 为 T 上所有公共属性的联合;
interface Car {
manufacturer: string;
model: string;
year: number;
}

let carProps: keyof Car; // the union of ('manufacturer' | 'model' | 'year')
索引访问操作符
  • K extends keyof T;
function getProperty<T, K extends keyof T>(o: T, propertyName: K): T[K] {
return o[propertyName]; // o[propertyName] is of type T[K]
}

工具类型

Partial
  • 类型的所有属性变为可选;
type PersonPartial = Partial<Person>;

// 自定义实现
type Partial<T> = {
[P in keyof T]?: T[P];
};
Required
  • 类型的所有属性变为必选;
type RequiredContact = Required<Contact>;

// 自定义实现
type Required<T> = {
[P in keyof T]-?: T[P];
};
Readonly
  • 类型的所有属性变为只读;
type ReadonlyPerson = Readonly<Person>;

// 自定义实现
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
Pick
  • 选取指定类型;
type ContactPick extends Pick<Contact, "name" | "phone"> {}
// ContactPick {
// name: string;
// phone?: string;
// }

// 自定义实现
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Omit
  • 移除指定类型;
type Contact {
name: string; // 姓名
phone?: string; // 手机号
email: string; // 邮箱
avatar: string; // 头像
userid: string; // id
}
export type OmitEmailContact = Omit<Contact, "email">;
// OmitEmailContact{
// name: string;
// phone?: string;
// avatar: string;
// userid: string;
// }

// 自定义实现
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
Record
  • 生成 Record 类型;
type Fruit = "apple" | "banana" | "orange";
type Inventory = Record<Fruit, number>;
/*
Inventory 类型为:
{
apple: number;
banana: number;
orange: number;
}
*/
Exclude
  • 排除联合类型的指定类型;
type Platform = "Windows" | "MacOS" | "Linux" | "iOS" | "Android";
type DesktopPlatform = Exclude<Platform, "iOS" | "Android">;
// DesktopPlatform 类型为: 'Windows' | 'MacOS' | 'Linux'
?:
  • 若 T 能赋值 U,则为 X 类型,反之为 Y 类型;
T extends U ? X : Y

declare function f<T extends boolean>(x: T): T extends true ? string : number;
// Type is 'string | number
let x = f(Math.random() < 0.5)

操作符

// 非空断言操作符 !
map!; // 表示 map 一定有值
// 可选链操作符 ?
map?.getLayer(); // 表示 map 为可选项, map 非空时才会执行 getLayer() 函数, 为空时返回 undefined
// 空值合并运算符 ??
const foo = null ?? "default string"; // 当左侧操作数为 null 或 undefined 时, 返回右侧操作数, 反之返回左侧操作数

声明文件

基本概念

声明文件
  • 用于声明第三方库类型,变量,方法等。。。
后缀名
  • .d.ts 为后缀;

自定义类型

export type CaseListData = {
key: string;
title: string;
data: string[];
};