TypeScript 类型经验本

这篇文章讲解类型。莫要让 TypeScript 成为 AnyScript,学习类型也是从简单复杂typescript

范型参数变量经常使用理解

  • T 表示 type 类型
  • P 表示 props 属性
  • K/V key/value
  • U 经常使用的类型变量

类型中的关键字和操做符

复杂类型中经常使用的关键字和操做符json

  • keyof 至关于 Object.keys
  • in 至关于 for-in
  • ? 可选操做符
  • -? 可选取反
  • extends
    • interface/class 表示继承
    • type 中表示约束
    • ...
  • []
    • 类型属性访问
    • 类型计算

签名

定义函数的输入和输出api

严格的类型检查

为了更好的使用 TypeScript, 须要开启严格的 TypeScript 代码检查:markdown

  • noImplicitAny 没有隐式的 any 类型推断
    • 错误提示:Parameter 'a' implicitly has an 'any' type.ts(7006)
  • strictNullChecks 严格的 null 检查
    • 默认状况下,值 null 和 undefined 可分配给任何其余类型。
{
    "compilerOptions": {
        "noImplicitAny": true,
        "strictNullChecks": true,
    }
}
复制代码

严格的 null 检查 最佳实践1 , 在处理空指针的状况下,很是实用。app

type User = {
  name: string;
  age?: number; // 可选的属性,不存在时,不能使用其上面的属性和方法
}

const getUser = (user: User) => {
  console.log(user.name, user.age.toString()) // user.age 🐛 可能不存在可是调用方法
}
复制代码

age 是可选的,可是在 console.log 中调用了 toString 方法。dom

  • ts: Object is possibly 'undefined'.ts(2532) 咱们可使用 ?. 来解决这个🐛,严格检查
console.log(user.name, user.age?.toString())
复制代码

基础类型

  • boolean 布尔类型
  • string 字符串类型
  • void/null/undefined 三种空类型
  • any/any[] 类型
  • tuple 元祖类型
  • 枚举类型
  • never/unknown
  • 函数类型
    • 函数/构造函数字面量类型
    • 函数调用类型
    • 构造函数签名

按级别划分类型

顶级类型 top type

  • any/unknown. 包含全部类型的集合。

底部类型 bottom type

  • never 空集合

从类型 type 引出接口 interface

在 TypeScript 中,使用 type 关键字,定义类型别名函数

type User = number | string; // 定义 number | string 的联合类型为 User
复制代码

⚠️:别名 type 一旦定义定义就不能扩展本身,只能用 type 定一个其余的类型。基于别名 type 自生不可扩展,引出 接口 interface 的概念就很合适了。oop

interface Global {
    api1: number
}
复制代码

咱们想要扩展 Global 接口,就能够直接从新定义(从新定义不是简单的覆盖行为)学习

interface Global {
     api2: number
 }
复制代码

api2接口属性是补充在 Global 属性上面的,而不是覆盖以前定义的 api1。ui

TypeScript 对象类型 Object Types

对象类型应该是咱们最经常使用的复合类型在之一了。

定义对象类型的方式:

  • interface
  • type

他们的最主要的区别之一就是:能不能不产生新的类型的基础上扩展本身。

可选/只读的类型属性

  • 可选: ?.<your option>
  • 只读: readonly <you option>

索引类型

有时候,咱们不肯定属性的名称,此时咱们就能够定义索引类型

interface User {
    [index: string]: any
}
复制代码

index 表示索引,索引的类型是 string,属性对应的类型是 any

interface 的类型扩展

  1. 从新定义接口,而后补充新的属性,不产生一个新的接口
  2. 使用 extend 关键字补充,产生一个新的接口

type 的类型补充

  1. 使用 | 联合类型,进行扩展,产生一个新的类型。

交叉类型

两个类型交叉,将两个不一样类型组合成一个新的类型没有重复的新的类型

type A = {
    name: string
    age: number
}

type B = {
    age: number
    sex: string
}

const C: A & B = {
    name: 'sdfd',
    age: 123,
    sex: 'male'
}

const D: A | B = {
    name: 'sdf',
    age: 123
}
复制代码

类型进阶

  • 泛型
  • 联合类型
  • 交叉类型
  • 索引类型
  • 映射类型
  • 条件类型

重要的条件类型

extends 约束类型

extends关键字,在类型约束中起到重要做用。

语法

SomeType extends OtherType ? TrueType : FalseType;
复制代码
  • 特色1: extends 关键字,本质是遍历,每个属性对比是子集,返回 TrueType, 不然返回 FalseType。 extends 表示条件
  • 特色2: 三目运算符 ? : , 分配类型

为什是重要的条件类型?

  • 缘由是,他能够衍生出不少的其余的泛条件类型

本质很简单,就是将是三目运算符,放在了类型的判断中:(一个前提:条件是继承关系)

T extends U ? X : Y
复制代码

也就是说 子类型 T 是否是继承自父类型 U若是是,取 X 类型,若是不是取 Y 类型。

既然是条件,那有 true/false 就很正常

type User = {
    name: string;
    age: number
}
declare function <T extends boolean>f(x: T): T extends true ? User : null;

// T 类型继承 true 类型时,函数 f 的返回值是 User, 不然是 null

const a = f(Math.random() < 0.1); // User | number
const b = f( 1 < 2) // User
const c = f( 1 > 2) // null
复制代码

泛条件类型

Exclude 在已有的类型中,排除指定的部分(子集关系 + never)

关于范型,这里不讨论。

type Exclude<T, U> = T extends U ? never : T;
复制代码
  • exclude 示例
type Ex<T, U> = T extends U ? never : T

type Parent = {
    name: string;
    age: number;
}

type User = {
    name: string;
    age: number;
    sex: string;
}

// A 是 User 类型, 下面的 sex 的存在
const A: Ex<User, Parent> = {
    name: 'xiaoming',
    age: 234,
    sex: 'sdf' // Type '{ name: string; age: number; pa: number; ad: number; sex: string; }' is not assignable to type 'User'.
}
复制代码

A 是 Ex<User, Parent> 类型,Parent 类型,不是 extends User,因此得 A 就是 User 类型.

示例

  • 一个类型能够是 ID 或者 name, 根据不一样的条件有不一样的类型。
type IId = { id: number }

type IName = { name: string }

type NameOrId<T extends string | number> = T extends number ? IId :  IIName
复制代码

扩展条件类型

从上面看了 Exclude 的源码,是 子集 + never, 由此,咱们也能扩展其余的类型:

  • 子集 + null
  • 子集 + undefined
  • 子集 + any(好像没有必要)
type CNull<T, U> = T extends U ? null : T;
type CUndefined<T, U> = T extends U ? undefined : T;
type CAnd<T, U> = T extends U ? and : T;
复制代码

参考

相关文章
相关标签/搜索