TS教程

194 阅读5分钟

参考自:1.2W字 | 了不起的 TypeScript 入门教程 - 掘金 (juejin.cn)

TypeScript 是什么

它是 JavaScript 的一个超集,提供了可选的静态类型和基于类的面向对象编程

我们为什么需要TypeScript

1.快速、简单,最重要的是,容易学习。 2.支持面向对象的编程特性,比如类、接口、继承、泛型等等。 3.编译时提供错误检查 4.支持所有JS库 5.使用继承来支持可重用性。

优点

1.总是在编译时强调错误,而JS在运行时指出错误。 2.支持强类型或静态类型,而这不是在JS中。 3.它有助于代码结构。 4.它使用基于类的面向对象编程。 5.它提供了优秀的工具支持和智能感知,后者在添加代码时提供活动提示。

缺点

1.编译代码时间长。 2.不支持抽象类。 3.需要编译步骤将TS转JS。 4.第三方库必须定义文件

基础类型

  • Boolean 类型
  • Number 类型
  • String 类型
  • Array 类型
  • Enum 类型

类型守卫

类型保护是可执行运行时检查的一种表达式,用于确保该类型在一定的范围内。换句话说,类型保护可以保证一个字符串是一个字符串,尽管它的值也可以是一个数值。类型保护与特性检测并不是完全不同,其主要思想是尝试检测属性、方法或原型,以确定如何处理值。目前主要有四种的方式来实现类型保护

  • in 关键字
  • typeof 关键字
  • instanceof 关键字

联合类型和类型别名

交叉类型

交叉类型是将多个类型合并为一个类型。

interface IPerson {
  id: string;
  age: number;
}

interface IWorker {
  companyId: string;
}

type IStaff = IPerson & IWorker;

接口

在面向对象语言中,接口是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类去实现。

TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。

在面向对象语言中,类是一种面向对象计算机编程语言的构造,是创建对象的蓝图,描述了所创建的对象共同的属性和方法。

枚举类型

是一种数据类型,允许我们定义一组命名常量。使用枚举可以更容易地记录意图,或者创建一组不同的案例。它是相关值的集合,可以是数值或字符串值。

模块

模块是创建一组相关变量、函数、类和接口等的强大方法。它可以在它们自己的范围内执行,而不是在全局范围内。换句话说,在模块中声明的变量、函数、类和接口不能在模块外部直接访问

名称空间

名称空间是用于对功能进行逻辑分组的一种方式。用于在内部维护typescript的遗留代码。它封装了共享某些关系的特性和对象。名称空间也称为内部模块。名称空间还可以包括接口、类、函数和变量,以支持一组相关功能

泛型

可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件

泛型(Generics)是允许同一个函数接受不同类型参数的一种模板。相比于使用 any 类型,使用泛型来创建可复用的组件要更好,因为泛型会保留参数类型

泛型变量

  • T(Type):表示一个 TypeScript 类型
  • K(Key):表示对象中的键类型
  • V(Value):表示对象中的值类型
  • E(Element):表示元素类型

泛型工具类型

typeof

在 TypeScript 中,typeof 操作符可以用来获取一个变量声明或对象的类型

interface Person {
  name: string;
  age: number;
}

const sem: Person = { name: 'semlinker', age: 30 };
type Sem= typeof sem; // -> Person

function toArray(x: number): Array<number> {
  return [x];
}

type Func = typeof toArray; // -> (x: number) => number[]

keyof

keyof 操作符可以用来获取一个对象中的所有 key 值

interface Person {
    name: string;
    age: number;
}

type K1 = keyof Person; // "name" | "age"
type K2 = keyof Person[]; // "length" | "toString" | "pop" | "push" | "concat" | "join" 
type K3 = keyof { [x: string]: Person };  // string | number

in

in 用来遍历枚举类型

type Keys = "a" | "b" | "c"

type Obj =  {
  [p in Keys]: any
} // -> { a: any, b: any, c: any }

infer

在条件类型语句中,可以用 infer 声明一个类型变量并且对它进行使用

type ReturnType<T> = T extends (
  ...args: any[]
) => infer R ? R : any;

以上代码中 infer R 就是声明一个变量来承载传入函数签名的返回值类型,简单说就是用它取到函数返回值的类型方便之后使用

extends

有时候我们定义的泛型不想过于灵活或者说想继承某些类等,可以通过 extends 关键字添加泛型约束

interface ILengthwise {
  length: number;
}

function loggingIdentity<T extends ILengthwise>(arg: T): T {
  console.log(arg.length);
  return arg;
}

Partial

Partial的作用就是将某个类型里的属性全部变为可选项 ?

/**
 * node_modules/typescript/lib/lib.es5.d.ts
 * Make all properties in T optional
 */
type Partial<T> = {
  [P in keyof T]?: T[P];
};

在以上代码中,首先通过 keyof T 拿到 T 的所有属性名,然后使用 in 进行遍历,将值赋给 P,最后通过 T[P] 取得相应的属性值。中间的 ? 号,用于将所有属性变为可选

装饰器

  • 它是一个表达式
  • 该表达式被执行后,返回一个函数
  • 函数的入参分别为 target、name 和 descriptor
  • 执行该函数后,可能返回 descriptor 对象,用于配置 target 对象

装饰器的分类

  • 类装饰器(Class decorators)
  • 属性装饰器(Property decorators)
  • 方法装饰器(Method decorators)
  • 参数装饰器(Parameter decorators)