跳到主要内容

基础

数据类型

// 布尔值
const isDone: boolean = false;
// 数值
const num: number = 1;
// 字符串
const myName: string = "Tom";
// 函数返回空 / 没有任何类型
const alertName = (): void => {
console.log("My name is Tom");
};
// 变量没有值的初始状态; 任何类型的子类型
const u: undefined = undefined;
// undefined 是任何类型的子类型, 可赋值给 number
let num: number = undefined;
// 表示什么都没有; 任何类型的子类型
const n: null = null;
// 可赋予任何类型, 可使用任何类型的属性和方法
let anyThing: any = "Tom";
// 不知道类型的变量, 需类型断言确定类型
const unknown: unknown = 1;
// 永远不存在值的类型, 抛出异常时返回 never
const never: never = 1;
// void 表示没有任何类型
function warnUser(): void {
console.log("This is my warning message");
}

接口

定义接口

interface Person {
// 只读属性, 不能被修改
readonly id: number;
// 必须属性, 不能省略
name: string;
// 可选属性, 可以省略
age?: number;
// 任意属性, 任意类型的属性
[propName: string]: string | number;
}

接口继承接口

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 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) => {};
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;

手动赋值

  • 未手动赋值的根据上一个枚举项递增;
  • 手动赋值可能出现重复值, ts 不报错, 应避免;
enum Directions {
Up = 3,
Down = 2,
Left,
Right,
}

替代

  • enum 无法翻译为原生 js;
  • 推荐使用 as const 替代 enum;
const Directions = { Up: 3, Down: 2, Left: 1, Right: 0 } as const;

类型断言

语法格式

  • 具有 <>as 两种声明形式;
  • 推荐使用 as;
const tom = getCacheData("tom") as Cat;
const tom = <Cat>getCacheData("tom");

双重断言

  • 可将任意类型断言为另一任意类型;
  • 不建议使用;
A as any as B;

基本概念

访问修饰符

  • public: 公有, 任何地方均可访问;
  • private: 私有, 仅能从声明类内部访问;
  • protected: 保护, 仅能从声明类及其子类内部访问;
class Animal {
private name;
public constructor(name) {
this.name = name;
}
}

let a: Animal = new Animal("Jack");

readonly

  • 只读修饰符;
  • 与其他访问修饰符共存时, 放在其后;
class Animal {
public constructor(public readonly name) {}
}

abstract

  • 定义抽象类及其抽象方法;
  • 抽象类和方法不能被实例化;
abstract class Animal {
public name;
public constructor(name) {
this.name = name;
}
public abstract sayHi();
}

类和接口

类实现接口

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;
}
// 'manufacturer' | 'model' | 'year'
let carProps: keyof Car;

索引访问操作符

  • 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]
}

工具类型

// 所有属性变为可选; { [P in keyof T]?: T[P]; }
type PersonPartial = Partial<Person>;
// 所有属性变为必选; { [P in keyof T]-?: T[P]; }
type RequiredContact = Required<Contact>;
// 所有属性变为只读; { readonly [P in keyof T]: T[P]; }
type ReadonlyPerson = Readonly<Person>;
// 选取指定属性; { [P in K]: T[P]; }
type ContactPick = Pick<Contact, "name" | "phone">;
// 移除指定属性; Pick<T, Exclude<keyof T, K>>
type OmitEmailContact = Omit<Contact, "email">;
type Fruit = "apple" | "banana" | "orange";
// 生成属性为 K, 值为 T 的类型
type Inventory = Record<Fruit, number>;
type Platform = "Windows" | "MacOS" | "Linux" | "iOS" | "Android";
// 排除联合类型中指定类型
type DesktopPlatform = Exclude<Platform, "iOS" | "Android">;
// 条件类型: 若 T 能赋值 U 则为 X, 反之为 Y
declare function f<T extends boolean>(x: T): T extends true ? string : number;
let x = f(Math.random() < 0.5);

操作符

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

声明文件

基本概念

声明文件

  • 用于声明第三方库类型, 变量, 方法等;

后缀名

  • .d.ts 为后缀;

自定义类型

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