探索 TypeScript 类型注解 - 高级类型

1,090 阅读3分钟

Exploring TypeScript Type Annotations - Advance Types

本文由 WowBar 团队首发于 GitHub

作者: zhilidali

欢迎来到 《探索 TypeScript 类型注解》 系列教程。 上一篇介绍了类型检查机制,本篇深入探索高级类型。

目录

交叉类型

交叉类型将多个类型合为一个类型: T & U

interface TypeA { a: number }
interface TypeB { b: number }
let a: TypeA = { a: 1 };
let b: TypeB = { b: 2 };
let c: TypeA & TypeB = { ...a, ...b };

联合类型

联合类型表示一个值可以是几种类型之一: T | U

具有联合类型的值只能访问类型的共有成员。

// Union Type
let tsUnion: number | string = 1;
tsUnion.length; // error: 只能访问共有成员

索引类型

索引类型查询操作符

keyof T:表示为 T 的公有属性名的联合。

interface F { a: string; b: number; }

type foo = keyof F;
// type foo = 'a' | 'b'

索引访问操作符

T[K]:表示 T 的属性 K 的类型。

interface F { a: string; b: number; }

type foo = F['a'];
// type foo = string

索引类型 && 索引签名

如果类型 T 带有字符串索引签名,那么 keyof Tstring | number 类型。 如果类型 T 带有数字索引签名,那么 keyof Tnumber 类型。 如果类型 T 带有索引签名,那么 T[K] 为索引签名的类型。

interface B { [index: string]: string; }

type foo = keyof B;
// type foo = string | number
type bar = B['string'];
// type bar = string

映射类型

映射类型可以基于旧类型创建新类型。

[K in T]: Type:类型变量 K 会把字符串字面量联合类型 T 的每个字符串都映射为属性。

type Foo = 'a' | 'b';
type Bar = {
	[K in Foo]: number;
}
// 等同于:
// type Bar = {
// 	a: number;
// 	b: number;
// }

在映射类型中,新类型可以相同的形式转换旧类型中的每个属性,例如,例如,可以将类型的所有属性设置为可选或只读。 由于转换为只读或可选等功能非常有用,它们被包含在 TypeScript 的标准库中, 详情见下篇实用工具类型

interface Foo {
	a: number;
	b: number;
}

type FooPartial = {
	[P in keyof Foo]?: Foo[P];
}
// 等同于:
// type FooPartial = {
// 	a?: number | undefined;
// 	b?: number | undefined;
// }

type FooReadonly = {
	readonly [P in keyof Foo]: Foo[P];
}
// 等同于:
// type FooReadonly = {
// 	readonly a: number;
// 	readonly b: number;
// }

条件类型

T extends U ? X : Y: 如果 T 可以赋值给 U,那么类型是 X,否则为 Y

type TypeName<T> = T extends string ? "string" : "number";

type Foo = TypeName<'ts'>;
// type Foo = "string"

type Bar = TypeName<number>;
// type Bar = "number"

嵌套条件类型

type TypeName<T> =
	T extends string ? 'string' :
	T extends number ? 'number' :
	T extends boolean ? 'boolean' :
	T extends undefined ? 'undefined' :
	T extends Function ? 'function' :
	'object';

type Foo = TypeName<string>;
// type Foo = "string"

type Bar = TypeName<true>;
// type Bar = "boolean"

分布式条件类型

如参数 TA | B,条件类型会自动解析为 (A extends U ? X : Y) | (B extends U ? X : Y)

type Baz = TypeName<1 | false>
// type Baz = "number" | "boolean"

条件类型中的类型推断extends 子句中,允许使用 infer 声明一个 类型变量,可以在 true 分支中被引用

type A<T> = T extends { a: infer U } ? U : any;

type Foo = A<{ a: number }>
// type Foo = number
type Bar = A<number>
// type Bar = any

声明多个同名 类型变量 会被推断为联合类型

type A<T> = T extends { a: infer U, b: infer U } ? U : any;

type Foo = A<{ a: number, b: string }>
// type Foo = string | number

结语

本篇介绍了类型的高级类型,下篇将探索 TypeScript 提供的实用工具类型。

协议

CC BY-NC-ND 4.0
LICENSE

本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。

《探索 TypeScript 类型注解》

  1. [x] 扩展的 JavaScript
  2. [x] 数据类型
  3. [x] 自定义类型
  4. [x] 类型检查
  5. [x] 高级类型
  6. [x] 类型编程

参考链接

Handbook: github.com/microsoft/T…