特殊类型

void类型 void有两种场景

  1. compilerOptions中的strictNullChecks为true,则void可以说是undefined
  2. strictNullChecks: false, 则void 可以说是 undefined | null

实际上这个类型最大的意义是在函数返回值上open in new window

any

any类型和任何类型取&都会得到any。type challenge: IsAny

type foo = keyof any  // foo = string | number | symbol
在条件类型中,any也比较特别。
type TestAny<T> = T extends number ? 1 : 2;
type bar = TestAny<any> // bar = 1 | 2
1
2
3
4

never

如果条件类型左边是类型参数,并且传入的是 never,那么直接返回 never 这个类型通常会在分布式类型falseType或trueType中出现,在union类型中会自动过滤。

type TestNever<T> = T extends number ? 1 : 2;
type foo = TestNever<never> // foo = never
type foo2 = never extends number ? 1 : 2; // foo = 1
type foo3 = never extends never ? 1 : 2; // foo = 1
1
2
3
4

Turple类型

tuple实际上也是数组类型,但它的长度是一个数值常量。

type foo = [1, 2]
type IsTurple<T> = T extends any[] ? number extends T['length'] ? false : true : false
1
2

Boolean

boolean实际上就是true | false

boolean = true | false

逆变与协变 父类型的变量被赋值子类型,称之为协变。 子类型的变量被赋值为父类型,则称之为逆变(多见于函数)

declare let Foo: {
  name: string
}

declare let Foo2: {
  name: string
  age: number
}

Foo = Foo2  // 协变
Foo2 = Foo  // missing property “age”

declare let Bar: (arg: {
  label: string
}) => void

declare let Bar2: (arg: {
  label: string
  value: number
}) => void

Bar = Bar2  // missing property “value”
Bar2 = Bar  // 逆变
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

其中union转intersection就是通过这个原理playground

加减乘除 实际上类型运算中并没有语言中的操作符,那在ts中实现基本思想就是递归加数组的长度array1['length']open in new window

索引操作 索引通常会使用keyof关键词来操作对象中的key。 但在使用过程中可能会有一种情况。递归计算type类型没有展开整个对象。所以我们需要一个多余的判断open in new window

utility高级type

InstanceType

这个比较简单,通常就是用来获取构造器对应的类

class A {}


type Foo = InstanceType<typeof A> // 等价于 A
1
2
3
4

UpperCase、LowerCase等

我们可以看到这些个类型在ts dts声明中有一个intrinsic关键字。 其实这个很简单,依赖编译器缓存的原字符串,在遇到Uppercase等高阶类型后,将字符串大写或小写化即可。

ThisType

这个类型的源码非常简单 ThisType

this在vue的使用非常广泛。vue-class-component由于使用了class组件的写法,ts天然支持比较好。那原本最初始的vue2实际上支持的不好,但我们来看看这个demo defineComponent

源码地址:composition-api/component/componentOptions

源码初窥

https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API

文件地址:src/compiler/checker.ts

函数名:getTypeFromTypeAliasReference

const ts = require("./built/local/typescript");

// const filename = "./input.ts";
const filename = "./demos/use-uppercase.ts";
const program = ts.createProgram([filename], {
    allowJs: false
});
const sourceFile = program.getSourceFile(filename);
const typeChecker = program.getTypeChecker();

function visitNode(node) {
    if (node.kind === ts.SyntaxKind.TypeReference)  {
        const type = typeChecker.getTypeFromTypeNode(node);
    }

    node.forEachChild(child =>
        visitNode(child)
    );
}

visitNode(sourceFile);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  1. never类型在union中的过滤
never-in-union
  1. 分布式条件类型的运算
distributivedistributive2

文章分享

赋予Vuex 4.x 更好的 TypeScript体验open in new window