chenjigeng / blog

个人博客
278 stars 25 forks source link

Typescript 小笔记 #24

Open chenjigeng opened 3 years ago

chenjigeng commented 3 years ago

Enum

Enum 在编译后,会变成一个对象,key 和 value 都会变成编译对象的 key

enum A {

    b = 2,

    c = 6

}

编译后

"use strict";

var A;

(function (A) {

    A[A["b"] = 2] = "b";

    A[A["c"] = 6] = "c";

})(A || (A = {}));

为什么有时候通过对象的方式将一个 'right' 赋给 'right' | 'left' 的时候报错

const columns = [

  {

    title: 'Available',

    dataIndex: 'available',

    fixed: 'right',

    render: (value: boolean) => {

      return value ? 'Y' : 'N'

    },

  },

]

return (

  <Table

    columns={columns} // 不能将类型“string”分配给类型“boolean | "right" | "left" | undefined”

    dataSource={dataSource}

    rowKey="id"

  />

}

原因:因为 ts 在进行类型推导的时候,会尝试进行【类型拓宽】,故意推导出一个更宽泛的类型。修复的方法就是告诉 Typescript,这里的 'right' 是个常量,不要在传递的过程中将其理解为 string 类型。

// 方式一,加上 as const 类型断言

const columns = [

  {

    title: 'Available',

    dataIndex: 'available',

    fixed: 'right' as const, // right 是个常量

    render: (value: boolean) => {

      return value ? 'Y' : 'N'

    },

  },

]

// 方式二,给变量 columns 加上类型声明,避免 Typescript 自行推断

const columns: ColumnsType<Data>  = [

  {

    title: 'Available',

    dataIndex: 'available',

    fixed: 'right'

    render: (value: boolean) => {

      return value ? 'Y' : 'N'

    },

  },

]

// 方式三,直接赋值给组件,不要中间值处理

<Table

  columns={[

    {

      title: 'Available',

      dataIndex: 'available',

      fixed: 'right'

      render: (value: boolean) => {

        return value ? 'Y' : 'N'

      },

    },

  ]}

  dataSource={dataSource}

  rowKey="id"

/>

ThisType

这个玩意可以用来声明对象的函数的 this 指针类型

interface PersonThis {

    name: string;

    age: number;

}

type Person = {

    getName: () => string;

} & ThisType<PersonThis>

const p: Person = {

    getName() {

        // 这里的 this 是 PersonThis

        return this.name

    }

}

联合类型遍历的方式

type IReturnType = string | number;

type GenNumberFun<T> = T extends string ? never : (...[]: any[]) => T;

// 等价于 (string extends string ? never : (...[]: any[]) => string) | (number extends string ? never : (...[]: any[]) => number)

type b = GenNumberFun<IReturnType> 

从StringConstructor 变成 string(StringConstructor 可以切换为其他基本类型的构造器)

type str = StringConstructor;

type s = str extends { (): infer R } ? R : never;

同上题,从 constructor 推导出对应的实例代码如下

class ClassA {}

type str = StringConstructor;

type classA = typeof ClassA;

type InstanceType<T> = T extends

  | (() => infer R)

  | {

      new (...args: any[]): infer R & object;

    }

  ? R

  : any;

type some = InstanceType<str>;

type typeClassA = InstanceType<classA>;

如何取出一个数组的通用类型

type testNumber = (string | number) [];

type t = testNumber[number] // string | number

实现一个 isAny

type isAny<T> = 0 extends (1 & T) ? true : false; // 利用 any & 任何东西都等于 any 的特性来处理

类型推断

假设我有一堆类型,type 是唯一标识,要通过 type 来推出具体的类型

type Type = 'a' | 'b';

interface IInputType {

    a: string;

    b: number;

}

type IT<T extends Type = Type> = T extends Type ? {

    type: T;

    h: IInputType[T];

} : any;

const t:IT = {

    type: 'a',

    h: 'asd'

}

const h:IT = {

    type: 'b',

    h: 123

}

通过 extends 的类型推导功能,比如通过 extends,变为

{

    type: 'a',

    h: IInputType['a']

} | {

    type: 'b',

    h: IInputType['b']

}

之后,在通过实际写的 type, ts 可以根据这个推导出这个类型属于 前者还是后者。

扩展全局变量

比如想扩展 Window 类型,可以这样写

interface Window {

    acquireVsCodeApi: <T = unknown>() => {

        getState: () => T;

        setState: (data: T) => void;

        postMessage: (msg: unknown) => void;

    }

}