Pressidian
花园入口
笔记
项目
关于
实验室
GitHub
花园入口
笔记
项目
关于
实验室
GitHub

KNOWLEDGE PATHS

笔记库
当前位置
笔记库/前端/工程化/类型检查/TS/类型体操

类型体操-简单

2 分钟阅读 · Note

目录树 578 篇

              • 类型体操-简单
              • 类型体操-实习
              • 类型体操-中等
              • cheat-sheets 小抄
              • TypeScript 中 `is` 与 `as` 的区别
            • TS项目经验
          • 运行时 Schema 校验
      • 前端技术栈
    • 笔记目录
    • CLAUDE.md
    • Vue 组件与 Render 函数

关联笔记 6

↗类型体操-实习同一路径↗类型体操-中等同一路径↗cheat-sheets 小抄同一路径↗TypeScript 中 `is` 与 `as` 的区别同一路径↗0Hello TypeScript共同主题↗编译选项共同主题
  • 类型体操-简单

类型体操-简单

[项目地址](type-challenges/README.zh-CN.md at main · type-challenges/type-challenges)很疯狂


实现 Pick

不使用 Pick<T, K> ,实现 TS 内置的 Pick<T, K> 的功能。 从类型 T 中选出符合 K 的属性,构造一个新的类型。

例如

interface Todo {
  title: string
  description: string
  completed: boolean
}

type TodoPreview = MyPick<Todo, 'title' | 'completed'>

const todo: TodoPreview = {
    title: 'Clean room',
    completed: false,
}

答案:

type MyPick<T, K extends keyof T> = 
	{ [key in keyof T as key extends K ? key : never] : T[key] }

键名重映射(Key Remapping) 在 TypeScript 的映射类型里,这个 as 其实就是一个“改名器”或者“过滤器”。 你可以把 [key in keyof T as ...] 想象成一条工厂流水线: key in keyof T:工人把 T 这个对象里的所有属性(比如 name, age, gender)一个一个拿出来,挨个放在传送带上。 as ...:传送带中间加了一个“检查站”。工人会拿着这个属性去 as 后面的条件里比对,决定这个属性是“保留原名”、“改个新名字”,还是“直接扔掉”。


Includes

在类型系统里实现 JavaScript 的 Array.includes 方法,这个类型接受两个参数,返回的类型要么是 true 要么是 false。

例如:

type isPillarMen = Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'> // expected to be `false`

答案:

// 这道显然不是简单题,我不敢想象地狱难度会是什么样子的。。。
type Includes<T extends readonly any[], U> = { [P in T[number]]: true }[U] extends true ? true : false;

Push

在类型系统里实现通用的 Array.push 。

例如:

type Result = Push<[1, 2], '3'> // [1, 2, '3']

答案:

// 这道就比较简单了
type Push<T extends any[], U> = [...T, U]

Unshift

实现类型版本的 Array.unshift。

例如:

type Result = Unshift<[1, 2], 0> // [0, 1, 2]

答案:

// 这道和push也是一样的,就是调换了一下位置
type Unshift<T extends any[], U> = [U,...T]

Parameters

实现内置的 Parameters 类型,而不是直接使用它,可参考TypeScript官方文档。

例如:

const foo = (arg1: string, arg2: number): void => {}

type FunctionParamsType = MyParameters<typeof foo> // [arg1: string, arg2: number]

答案:

// 使用infer获取到函数的参数的类型,并且把它赋给U
type MyParameters<T extends (...args: any[]) => any> = T extends (...args :infer U)=>any ? U : never