深入浅出TypeScript | 青训营笔记

33 阅读3分钟

简介

TypeScript提供了一套静态检测机制, 可以帮助我们在编译时就发现错误

基础

接口

TypeScript的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约

  • 可选属性 在可选属性名字定义的后面加一个?符号

    • 可以对可能存在的属性进行预定义
    • 可以捕获引用了不存在的属性时的错误
  • 只读属性 在属性名前用 readonly来指定只读属性

  • 额外的属性检查

  • 函数类型

  • 可索引的类型 可索引类型具有一个 索引签名,它描述了对象索引的类型,还有相应的索引返回值类型

  • 类类型

    • 实现接口
  • 继承接口 一个接口可以继承多个接口,创建出多个接口的合成接口

  • 混合类型

  • 接口继承类 当接口继承了一个类类型时,它会继承类的成员但不包括其实现。口同样会继承到类的private和protected成员。 这意味着当创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现

  • public
  • private
  • protected protected修饰符与 private修饰符的行为很相似,但有一点不同, protected成员在派生类中仍然可以访问

进阶

泛型

使用:

  1. 传入所有的参数,包含类型参数
  2. 利用了类型推论 -- 即编译器会根据传入的参数自动地帮助我们确定T的类型

泛型类型

泛型函数的类型与非泛型函数的类型没什么不同,只是有一个类型参数在最前面,像函数声明一样:

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: <T>(arg: T) => T = identity;

使用不同的泛型参数名,只要在数量上和使用方式上能对应即可。

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: <U>(arg: U) => U = identity;

使用带有调用签名的对象字面量来定义泛型函数:

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: {<T>(arg: T): T} = 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; };

泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型。

泛型约束

声明对类型参数进行约束

在泛型约束中使用类型参数

可以声明一个类型参数,且它被另一个类型参数所约束。

function getProperty(obj: T, key: K) {
    return obj[key];
}

let x = { a: 1, b: 2, c: 3, d: 4 };

getProperty(x, "a"); // okay
getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.

在泛型里使用类类型

在TypeScript使用泛型创建工厂函数时,需要引用构造函数的类类型

function create<T>(c: {new(): T; }): T {
    return new c();
}

使用原型属性推断并约束构造函数与类实例的关系。

class BeeKeeper {
    hasMask: boolean;
}

class ZooKeeper {
    nametag: string;
}

class Animal {
    numLegs: number;
}

class Bee extends Animal {
    keeper: BeeKeeper;
}

class Lion extends Animal {
    keeper: ZooKeeper;
}

function createInstance<A extends Animal>(c: new () => A): A {
    return new c();
}

createInstance(Lion).keeper.nametag;  // typechecks!
createInstance(Bee).keeper.hasMask;   // typechecks!

实战&工程像

声明文件

声明文件.png