TypeScript 类型经验本

莫要让 TypeScript 成为 AnyScript

严格的类型检查

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

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

严格的 null 检查 最佳实践1 , 在处理空指针的情况下,非常实用。

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

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

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

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

从类型 type 引出接口 interface

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

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

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

interface Global {
    api1: number
}
复制代码

我们想要扩展 Global 接口,就可以直接重新定义(重新定义不是简单的覆盖行为)

 interface Global {
     api2: number
 }
复制代码

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

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
}
复制代码

重要的条件类型

为什是重要的条件类型?

  • 原因是,他可以衍生出很多的其他的泛条件类型

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

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 在已有的类型中,排出指定的部分

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;
    pa: number;
    ad: number
    sex: string
}

type User = {
    name: string;
    age: number;
    pa: number;
    ad: number
}

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

参考

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享