🎨
Notes
  • 持续更新中...
  • articles
    • browser
      • 深入理解现代浏览器 - 导航
      • 深入理解现代浏览器 - 架构
      • 深入理解现代浏览器 - 交互
      • 深入理解现代浏览器 - 渲染器进程
    • dsa
      • DSA - 并查集
      • DSA - 哈希表
      • DSA - AVL 树
      • DSA - 二叉树
      • 快速选择
      • Big O 算法复杂度
      • DSA - 栈和队列
      • DSA - 前缀树 Trie
      • DSA - 图
      • DSA - 链表
      • DSA - 递归
    • typescript
      • TypeScript 学习笔记 - 任意属性 (Indexable Types)
      • 力扣的 TypeScript 面试题
      • TypeScript 学习笔记 - as const
      • TypeScript 学习笔记 - infer
    • network
      • Internet Protocol (IP)
      • 计算机网络基础
      • 如何分辨同源和同站
      • DNS 如何查询 IP 地址?
    • vue
      • Nuxt.js 入门
      • 从零实现一个 Mini Vue
      • 从零实现一个简单的 VDOM 引擎
      • 从零实现一个响应式状态管理
    • sorting
      • 排序 - 归并排序
      • 排序 - 冒泡排序
      • 排序 - 选择排序
      • 排序 - 计数排序
      • 排序 - 插入排序
    • compile
      • Compiler and Interpreter
      • Just-In-Time (JIT) Compilers
      • 编译流程
    • others
      • 什么是上下文无关语法
      • 如何在终端打印出有颜色的字
    • dev-ops
      • github-actions
        • GitHub Action 简介
        • GitHub Actions for CI
    • workflow
      • 用 Node 写一个 cli
      • 如何规范 git commit 信息
      • 如何监听 git hooks
      • 如何规范代码风格 - prettier
      • 如何发布一个 npm package
      • 如何规范代码质量 - eslint
    • design-pattern
      • 代理模式
      • 单例模式
      • 策略模式
    • security
      • 点击劫持
      • CSP 内容安全策略
    • javascript
      • 尾调用优化
      • 4种常见的内存泄漏及解决方法
    • unit-test
      • Test Vuejs Application - Chapter 2
      • Test Vuejs Application - Chapter 1
      • Vue Unit Test Intro
    • performance
      • HTTP 缓存
      • 如何优化图片资源
Powered by GitBook
On this page

Was this helpful?

  1. articles
  2. typescript

TypeScript 学习笔记 - infer

先来看一个例子:

type FlattenIfArray<T> = T extends Array<infer R> ? R : T;

我们来分析一下以上代码:

  1. 首先判断泛型 T 是否数组类型;

  2. 如果是数组类型,将数组成员类型 R 抽出来并返回;

  3. 如果不是数组类型,则原样返回 T;

由于数组类型的定义有两种写法,所以上面的代码还有另外一种写法:

type FlattenIfArray<T> = T extends (infer R)[] ? R : T;

再来看一个例子:

type Unpromisify<T> = T extends Promise<infer R> ? R : T;
  1. 首先判断泛型 T 是否 Promise 的子集;

  2. 如果是,将 Promise 中的泛型 R 抽出来并返回;

  3. 如果不是则原样返回 T;

再来看一个复杂一点的例子:

type FunctionWithOneObjectArgument<P extends { [x: string]: any }, R> = (
    props: P,
) => R;

type DestructuredArgsOfFunction<
    F extends FunctionWithOneObjectArgument<any, any>
> = F extends FunctionWithOneObjectArgument<infer P, any> ? P : never;

const myFunction = (props: { x: number; y: number }): string => {
    return 'ok';
};

const props: DestructuredArgsOfFunction<typeof myFunction> = {
    x: 1,
    y: 2,
};

代码分析:

  • FunctionWithOneObjectArgument 接收两个泛型 P 和 R,然后返回一个函数签名 (props: P) => R,而 P extends { [x: string]: any } 这部分则将参数类型 P 限定为一个对象。

  • DestructuredArgsOfFunction 接收一个泛型 F,然后判断 F 是否 FunctionWithOneObjectArgument<P, R> 的子集,如果是子集则将其中的 P 类型抽出来返回,如果不是则返回 never

  • typeof myFunction 会返回 myFunction 的函数签名,也就是 (props: { x: number; y: number }): string

  • DestructuredArgsOfFunction<typeof myFunction> 就相当于 DestructuredArgsOfFunction<(props: { x: number; y: number }): string>,我们可以将它代入到 DestructuredArgsOfFunction 的类型定义中,容易看出 infer P 会将 P 推导为 { x: number; y: number },然后我们返回了 P,所以 props 变量的类型就是 { x: number; y: number } 了。

PreviousTypeScript 学习笔记 - as constNextnetwork

Last updated 4 years ago

Was this helpful?