# 类型编程

抛出问题?

我们学会了如何使用 Typescript 内置的类型系统进行类型校验。 但在实际使用中,有大量类型校验需要逻辑判断, 这种复杂的类型处理 TypeScript 官方文档 叫做 类型操作 (opens new window), 这里笔者更愿意称之为类型编程,重点在于, 可将类型操作类比为各种语句,通过组合不同的语句 ,实现对复杂类型的处理。这种概念映射可以更高效的帮助书写和理解复杂的类型函数。

本章将从语言的角度深入分析,基于 Typescript 提供的类型表示能力, 如何采用类似编程的方式解决复杂类型处理。该章节受 TypeScript Berlin Meetup #2: Generics, Conditional types and Mapped types (opens new window) 启发产生。

# 基本的映射关系

javascript typescript
原始值、数组、对象 原始类型、元祖类型、结构类型
变量 泛型
循环语句 映射类型
判断语句 条件类型
函数 type

# 递归类型

如何表示类似 JSON 的对象类型。由于JSON 本声支持任意深度嵌套 这里采用类型别名实现递归类型

type Json =
  | string
  | number
  | boolean
  | null
  | {
      [property: string]: Json;
    }
  | Json[];

let json1: Json = {
  a: 'foo',
  f: 1
};
// 支持嵌套结构
json1.t = json1;

另一个示例表示 Virtual DOM 节点

// 简化版表示 vue 的 Vnode 节点
type Vnode =
  | string
  | [string, string]
  | [
      string,
      {
        [key: string]: any;
      }
    ]
  | [
      string,
      {
        [key: string]: any;
      },
      Vnode | Vnode[]
    ];

let node: Vnode = 'div';
node = ['div', { id: '#app' }];
node = ['div', { id: '#app' }, 'text'];
node = ['div', { id: '#app' }];
node = ['div', { id: '#app' }, [['p', 'text'], 'br', ['img', { src: 'test' }]]];

也可使用 interface 来表示递归对象

// 创建一个包含嵌套属性的对象
interface Property {
  name: string;
  type: string;
  properties?: Property;
}

let prop: Property = {
  name: 'a',
  type: 'a',
  properties: {
    name: 'b',
    type: 'c',
    properties: {
      name: 'b',
      type: 'c'
    }
  }
};

尝试表示 Promise 等对象来进一步理解递归类型。

官方文档 Recursive Type Aliases (opens new window)