首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >TypeScript 类型体操 03

TypeScript 类型体操 03

原创
作者头像
发布于 2022-05-11 04:23:05
发布于 2022-05-11 04:23:05
4550
举报

发现一个好玩的开源项目:type-challenges,在上面可以做一些TypeScript类型相关的题目,这里记录一下自己的学习。

00002-medium-return-type

代码语言:typescript
AI代码解释
复制
/* _____________ Your Code Here _____________ */

type MyReturnType<T> = T extends (...params: any) => infer R ? R : never


/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<string, MyReturnType<() => string>>>,
  Expect<Equal<123, MyReturnType<() => 123>>>,
  Expect<Equal<ComplexObject, MyReturnType<() => ComplexObject>>>,
  Expect<Equal<Promise<boolean>, MyReturnType<() => Promise<boolean>>>>,
  Expect<Equal<() => 'foo', MyReturnType<() => () => 'foo'>>>,
  Expect<Equal<1 | 2, MyReturnType<typeof fn>>>,
  Expect<Equal<1 | 2, MyReturnType<typeof fn1>>>,
]

type ComplexObject = {
  a: [12, 'foo']
  bar: 'hello'
  prev(): number
}

const fn = (v: boolean) => v ? 1 : 2
const fn1 = (v: boolean, w: any) => v ? 1 : 2

00003-medium-omit

代码语言:typescript
AI代码解释
复制
/* _____________ Your Code Here _____________ */

type MyOmit<T, K extends keyof T> = { [R in Exclude<keyof T, K>]: T[R] }


/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Expected1, MyOmit<Todo, 'description'>>>,
  Expect<Equal<Expected2, MyOmit<Todo, 'description' | 'completed'>>>,
]

// @ts-expect-error
type error = MyOmit<Todo, 'description' | 'invalid'>

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

interface Expected1 {
  title: string
  completed: boolean
}

interface Expected2 {
  title: string
}

需要说明的是,这里的MyOmit和TS中提供的Omit是不一样的,TS中的版本定义为:type Omit<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; },不强制要求 Kkey of T中存在,但是这道题需要声明K extends keyof T 以满足type error = MyOmit<Todo, 'description' | 'invalid'>需要报错的测试用例

00008-medium-readonly-2

代码语言:typescript
AI代码解释
复制
/* _____________ Your Code Here _____________ */

type MyReadonly2<T, K extends keyof T = keyof T> = { [R in Exclude<keyof T, K>]: T[R] } & { readonly [R in K]: T[R] }


/* _____________ Test Cases _____________ */
import type { Alike, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Alike<MyReadonly2<Todo1>, Readonly<Todo1>>>,
  Expect<Alike<MyReadonly2<Todo1, 'title' | 'description'>, Expected>>,
  Expect<Alike<MyReadonly2<Todo2, 'title' | 'description'>, Expected>>,
]

interface Todo1 {
  title: string
  description?: string
  completed: boolean
}

interface Todo2 {
  readonly title: string
  description?: string
  completed: boolean
}

interface Expected {
  readonly title: string
  readonly description?: string
  completed: boolean
}

这里最神奇的地方是:MyReadonly2<T, K extends keyof T = keyof T>中的K extends keyof T = keyof T他的意思是给K提供一个默认值,如果没有提供K,就使用默认值keyof T,真的是太神奇了。

00009-medium-deep-readonly

代码语言:typescript
AI代码解释
复制
/* _____________ Your Code Here _____________ */

type DeepReadonly<T> = { readonly [K in keyof T]: keyof T[K] extends never ? T[K] : DeepReadonly<T[K]> }


/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<DeepReadonly<X>, Expected>>,
]

type X = {
  a: () => 22
  b: string
  c: {
    d: boolean
    e: {
      g: {
        h: {
          i: true
          j: 'string'
        }
        k: 'hello'
      }
      l: [
        'hi',
        {
          m: ['hey']
        },
      ]
    }
  }
}

type Expected = {
  readonly a: () => 22
  readonly b: string
  readonly c: {
    readonly d: boolean
    readonly e: {
      readonly g: {
        readonly h: {
          readonly i: true
          readonly j: 'string'
        }
        readonly k: 'hello'
      }
      readonly l: readonly [
        'hi',
        {
          readonly m: readonly ['hey']
        },
      ]
    }
  }
}

说实话这个地方我不太理解,有些很复杂的我觉得他是对的,但是太复杂了,也没搞懂。

00012-medium-chainable-options

代码语言:typescript
AI代码解释
复制
/* _____________ Your Code Here _____________ */

type Chainable<T extends object = {}> = {
  option<K extends string, V extends unknown>(key: K extends keyof T ? never : K, value: V): Chainable<T & { [P in K]: V }>
  get(): T
}


/* _____________ Test Cases _____________ */
import type { Alike, Expect } from '@type-challenges/utils'

declare const a: Chainable

const result1 = a
  .option('foo', 123)
  .option('bar', { value: 'Hello World' })
  .option('name', 'type-challenges')
  .get()

const result2 = a
  .option('name', 'another name')
  // @ts-expect-error
  .option('name', 'last name')
  .get()

type cases = [
  Expect<Alike<typeof result1, Expected1>>,
  Expect<Alike<typeof result2, Expected2>>,
]

type Expected1 = {
  foo: number
  bar: {
    value: string
  }
  name: string
}

type Expected2 = {
  name: string
}

话说这道题就离谱,还能这么搞的?简直大开眼界!有个知识点是:

image-20220511121437361.png
image-20220511121437361.png

大概意思是:如果T直接是一个Key, 就直接 {[p in T]: true},而不是:{[p in keyof T]: true}

00010-medium-tuple-to-union

代码语言:typescript
AI代码解释
复制
/* _____________ Your Code Here _____________ */

type TupleToUnion<T extends any[]> = T[number]


/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<TupleToUnion<[123, '456', true]>, 123 | '456' | true>>,
  Expect<Equal<TupleToUnion<[123]>, 123>>,
]

00015-medium-last

代码语言:typescript
AI代码解释
复制
/* _____________ Your Code Here _____________ */

type Last<T extends any[]> = T extends [...any[], infer res] ? res : never


/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Last<[3, 2, 1]>, 1>>,
  Expect<Equal<Last<[() => 123, { a: string }]>, { a: string }>>,
]

00016-medium-pop

代码语言:typescript
AI代码解释
复制
/* _____________ Your Code Here _____________ */

type Pop<T extends any[]> = T extends [... infer res, any] ? res : never


/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Pop<[3, 2, 1]>, [3, 2]>>,
  Expect<Equal<Pop<['a', 'b', 'c', 'd']>, ['a', 'b', 'c']>>,
]

00015、00016是相似的,不过00016的写法我倒是之前没有想到会这样的。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
Go语言库系列之aurora
背景介绍 今天跟大家推荐一款可以给终端输出上色的工具--aurora。 极速上手 准备工作 初始化项目 go mod init aurora 演示项目结构 . ├── go.mod ├── go.su
平也
2020/04/08
5120
chalk.js(node终端样式库)
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="javascript" contenteditable="true" cid="n33" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">const chalk = reuquire("chalk") const log = console.log ​ // 颜色字体 log( chalk.red("红色") ) ​ // 背景色 log( chalk.bgBlue("蓝色背景") ) ​ // 样式字体 log( chalk.bold("加粗") ) ​ // 多参数 log( chalk.blue("name", "age", "job") ) ​ // ES6 多行文本 log( // 多行文本将保留缩进格式 chalk.blue(name: Rogan age: ${25} job: ${ 'IT' }) ) ​ ​ // 其他颜色设置方式 log(chalk.keyword("orange")(' keyword ')) // 关键字 log(chalk.rgb(100, 100, 100)(' rgb ')) // rgb log(chalk.hex('#ffffff')(' hex ')) // hex ​ ​ ​ // 样式组合 log(colors: ${chalk.blue('blue')}, ${chalk.red('red')}) // 拼接 ​ log(chalk.blue.bold("Title")) // 链式组合 ​ log( chalk.bgYellow(error: ${chalk.red(" chalk is undefined ")}) ) // 嵌套 ​ ​ ​ // 自定义组合 const error = chalk.bgRed; const warning = chalk.yellow.bold;</pre>
copy_left
2019/08/21
3K0
欧拉函数最全总结
计算这个值的方法就叫做欧拉函数,以φ(n)表示。在1到8之中,与8形成互质关系的是1、3、5、7,所以 φ(n) = 4。
全栈程序员站长
2022/09/23
2.2K0
欧拉函数最全总结
color:让终端输出更多彩
在日常的开发过程中,我们经常需要在终端中输出信息。为了让这些信息更加直观和易读,使用不同的色彩是一种很好的方式。github.com/fatih/color 是一个轻量级且功能强大的Go语言库,可以方便地为终端输出添加颜色和样式。
孟斯特
2024/08/12
2960
color:让终端输出更多彩
Go每日一库之88:color
Golang下的命令行色彩使用库, 拥有丰富的色彩渲染输出,通用的API方法,兼容Windows系统
luckpunk
2023/09/30
5990
Go每日一库之88:color
(七)golang--变量之基本数据类型(看这篇就够了)
(1)golang整数类型分为:有符号和无符号,int和uint的大小和系统有关;
西西嘛呦
2020/08/26
6910
「Go工具箱」一个让终端内容彩色化的工具:Color
大家好,我是渔夫子。本号新推出「go工具箱」系列,意在给大家分享使用go语言编写的、实用的、好玩的工具。
Go学堂
2023/01/31
5070
termcolor: 轻量级终端输出彩色文本库
总而言之,colorama 主要用于解决 Windows 系统的兼容性问题,而 termcolor 提供了更方便的文本着色函数。 根据你的需求选择合适的库即可。
luckpunk
2025/01/16
3560
termcolor: 轻量级终端输出彩色文本库
go语言的print
代码: package main import ( "fmt" ) type point struct { x, y int } func main() { //Go 为常规 Go 值的格式化设计提供了多种打印方式。例如,这里打印了 point 结构体的一个实例。 p := point{1, 2} fmt.Printf("%v\n", p) // {1 2} //如果值是一个结构体,%+v 的格式化输出内容将包括结构体的字段名。 fmt.Prin
机器学习和大数据挖掘
2019/07/02
1.4K0
嵌入式linux之go语言开发(二)c动态库驱动调用
linux上的串口驱动,这个较简单,有标准的模块可用。操作的是标准的设备文件。如:ttys0等。
杨永贞
2020/08/04
2.4K0
[GO语言基础] 三.变量声明、数据类型、标识符及编程练习
作为网络安全初学者,会遇到采用Go语言开发的恶意样本。因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识;另一方面是分享与读者,希望大家一起进步。前文介绍了Go的编译运行、语法规范、注释转义及API标准库知识;这篇文章将介绍Golang的变量、数据类型和标识符知识,并通过12道编程练习进行提升。这系列文章入门部分将参考“尚硅谷”韩顺平老师的视频和书籍《GO高级编程》,详见参考文献,并结合作者多年的编程经验进行学习和丰富,且看且珍惜吧!后续会结合网络安全进行GO语言实战深入,加油~
Eastmount
2021/12/03
7820
[GO语言基础] 三.变量声明、数据类型、标识符及编程练习
优雅地使用 C++ 制作表格:tabulate
tabulate 是一个使用 C++ 17 编写的库,它可以制作表格。使用它,把表格对齐、格式化和着色,不在话下!你甚至可以使用 tabulate,将你的表格导出为 Markdown 代码。下图是一个使用 tabulate 制作的表格输出在命令行的样例:
HelloGitHub
2021/05/14
1.8K0
【Go语言精进之路】构建高效Go程序:掌握变量、常量声明法则与iota在枚举中的奥秘
在Go语言体系中,变量是存储数据的基本单元,其核心功能在于保存程序运行过程中的信息。每个变量都被赋予了特定的数据类型,这些类型涵盖了诸如整数(int)、浮点数(float)、字符串(string) 等多种基本类型以及其他复合类型。数据类型定义了变量能够存储值的范围和类型,确保了数据的准确性和一致性。
空白诗
2024/06/14
4560
【Go语言精进之路】构建高效Go程序:掌握变量、常量声明法则与iota在枚举中的奥秘
Go 每日一库之 bubbletea
bubbletea是一个简单、小巧、可以非常方便地用来编写 TUI(terminal User Interface,控制台界面程序)程序的框架。内置简单的事件处理机制,可以对外部事件做出响应,如键盘按键。一起来看下吧。先看看bubbletea能做出什么效果:
用户7731323
2021/06/25
1.1K0
Go 每日一库之 bubbletea
一文搞懂Go语言标准库,fmt
fmt 包含有格式化I/O函数,类似于C语言的 printf 和 scanf。主要分为向外输出内容和获取输入内容两大部分。
微客鸟窝
2021/12/21
6400
呜呜呜我要拿Go赢他~ 入门,Go的最简单的 Web 服务器!
继续接入上章节的呜呜呜我要拿Go赢他~ 入门,Go的基础语法! 的文章现在要学的是Go的最简单的 Web 服务器!
杨不易呀
2023/11/07
5111
呜呜呜我要拿Go赢他~ 入门,Go的最简单的 Web 服务器!
go语言time库
time包是Go语言标准库中的一个包,它提供了时间处理相关函数。time包中定义了一个名为Time的类型,表示一个日期和时间值。
GeekLiHua
2025/01/21
3520
go语言time库
一些小众却有用的 Node.js 包
yargs 是一个用来处理命令行参数的包,可以帮你处理自行设置的命令行标志和输入的任何类型的数据,其中包括布尔值、浮点数和字符串等。这个包非常简单明了,不需要在项目中编写大量的样板代码。
疯狂的技术宅
2020/10/22
9660
一些小众却有用的 Node.js 包
Go语言知识查漏补缺|基本数据类型
学习Go半年之后,我决定重新开始阅读《The Go Programing Language》,对书中涉及重点进行全面讲解,这是Go语言知识查漏补缺系列的文章第二篇,前一篇文章则对应书中一二两章。
白泽z
2022/12/20
5930
Go语言知识查漏补缺|基本数据类型
[GO语言基础] 三.变量声明、数据类型、标识符及编程练习12题
作为网络安全初学者,会遇到采用Go语言开发的恶意样本。因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识;另一方面是分享与读者,希望大家一起进步。前文介绍了Go的编译运行、语法规范、注释转义及API标准库知识;这篇文章将介绍Golang的变量、数据类型和标识符知识,并通过12道编程练习进行提升。 这系列文章入门部分将参考“尚硅谷”韩顺平老师的视频和书籍《GO高级编程》,详见参考文献,并结合作者多年的编程经验进行学习和丰富,且看且珍惜吧!后续会结合网络安全进行GO语言实战深入,加油~
Eastmount
2021/02/25
8630
相关推荐
Go语言库系列之aurora
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档