TypeScript体操,手动实现一些TS语法

这篇博客是关于TypeScript体操的实践,通过手动实现如Partial、Required、ReadOnly等TS语法,旨在深入理解TS语法机制,提高开发体验和代码质量。作者通过实例解释了关键字如typeof、keyof、in、extends的用途,并提供了多个工具类型的实现,包括Filter等,以增强对TypeScript的理解和应用。
摘要由CSDN通过智能技术生成

TypeScript体操,手动实现一些TS语法

前言

TypeScript是JavaScript的超集,TypeScript 通过对原生 JavaScript 提供强类型加持,在很大程度上提升了代码质量。但我在刚开始使用TS的时候,真的太难受了。曾经的我爱上前端就是因为前端开发起来方便快捷,JS的类型可以随心所欲,HTML写完立马就能看到效果。而现在,来了TS,边写边学,边学边写,工作量几近与翻倍。

但是!同志,请相信我,认真对待写TS这件事,你将收获:

0.更好友好的开发体验,提示更友好
1.TS声明即文档,减少了查文档的时间
2.复杂的大型项目,能够保证数据结构层级不错位
3.更好的抽象能力,部分枚举、模型和后端保持一致
4.规避低级错误,比如类型错误、函数传参错误、边界情况的判断

为什么要做TypeScript体操?

TS本身是一门语言,有自己的语法。从JS过来的前端工程师,往往都是瞄几眼TS官方文档就上手了,保证基本的日常开发没有问题就觉得掌握了TS这门语言的奥秘。但是在不经意间打开xx.d.ts的时候,尴尬的发现自己并看不懂别人写的TS声明文件,面试官让你手写一个TS的语法糖,你总是支支吾吾,好像会,又好像不太会。所以,希望通过这次的分享,希望可以达到以下几个目的:

0.从源码的角度理解每一个工具类型的实现机制
1.加深对TypeScript的理解
2.能够在平时的工作中举一反三,利用TypeScript为我们的代码保驾护航

关键字解释

typeof

在 TS 中用于类型表达时,typeof 可以用于从一个变量上获取它的类型。

const func = (a: number, b: number): number => {
  return a + b;
}
const obj = {
  name: 'zaoren',
  age: 11
}
​
type tupeFunc = typeof func; // type tupeFunc = (a: number, b: number) => number
type obj = typeof obj; // type obj = { name: string; age: number;} 
keyof

keyof 的作用将一个 类型 映射为它 所有成员名称的联合类型

// 用 TS interface 描述对象
interface TsInterfaceObject {
  first: string;
  second: number;
}
​
// 用 TS type 描述对象
type TsTypeObject = {
  first: string;
  second: number;
};
​
// 用 Ts type 描述基本类型别名
type TsTypeAlias = string;
​
class JsClass {
  private priData: number;
  private priFunc() {}
​
  public pubData: number;
  public pubFunc1() {}
  public pubFunc2() {}
}
​
type NameUnionOfInterface = keyof TsInterfaceObject;
​
/**
 * 将所描述对象中的所有 key 组合成一个联合类型
 * type NameUnionOfType = "first" | "second"
 */
type NameUnionOfTypeObj = keyof TsTypeObject;
​
/**
 * 对一个非对象类型使用 keyof 后,会返回其 prototype 上所有 key 组合成的一个联合类型
 * type NameUnionOfTypeAlias = number | typeof Symbol.iterator | "toString" | "charAt" | ...
 */
type NameUnionOfTypeAlias = keyof TsTypeAlias;
​
/**
 * 其实也是返回 prototype 上所有 key(因为其实 private 私有部分实际是放在实例化对象中,而非原型)
 * type NameUnionOfClass = "pubData" | "pubFunc1" | "pubFunc2"
 */
type NameUnionOfClass = keyof JsClass; 
in

in 可以按照js中的for…in遍历去理解,我们拿Pick这个语法糖来具体举例:[p in K]相当于就在遍历'name' | 'age'属性。

interface Person {
  name: string;
  age: number;
  location: string;
}
​
// 从 Person 中取出 'name' 属性
type pPersion = Pick<Person, 'name' | 'age'> // type pPersion = {name: string; age: number }
​
/**
* Pick 的语法
*/
type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
}; 
extends

extends关键字在TS编程中出现的频率挺高的,而且不同场景下代表的含义不一样

  • 类型继承,类型 A 去继承类型 B(interface 可用 extends 继承,type 不可以)interface IHuman {  gender: "male" | "female";  age: number;}​interface IProgrammer {  language: "java" | "php" | "javascript";}​/** * interface 的继承 * 可以同时继承多个 interface,它们之间用逗号分隔 */interface IWebDeveloper extends IProgrammer, IHuman {  skill: "vue" | "react";}​const Me: IWebDeveloper = {  skill: "react",  language: "javascript",  age: 18,  gender: "male",}; * 对类型进行条件约束在书写泛型的时候,我们往往需要对类型参数作一定的限制,比如希望传入的参数都有 name 属性的数组我们可以这么写:function getCnames<T extends { cname: string }>(entities: T[]):string[] {  return entities.map(entity => entity.cname)  } 这里extends对传入的参数作了一个限制,就是 entities 的每一项可以是一个对象,但是必须含有类型为stringcname属性。

  • 条件匹配// 判断范型 T 是否匹配于 numbertype OnlyWantNumber<T> = T extends number ? any : never;​type Type1 = OnlyWantNumber<number>; // type Type1 = any​type Type2 = OnlyWantNumber<string>; // type Type2 = never 需要注意的是,如果 extends 左侧的类型为联合类型,会被拆解,就像数学中的分解因式子一样`P<‘x’ | ‘y’> => P<‘x’> | P<‘y’>````type P = T extends ‘x’ ? string : number;​ type A3 = P<‘x’ | ‘y’>  // A3的类型是 string | number ```#### infer

infer。它可以在 extends 关键字右侧的类型表达式中的任何位置使用。使用它可以为出现在该位置的任何类型命名

// 这里的 extends 在描述泛型
type Unpack<A> = A extends Array<infer E> ? E : A
​
type Test = Unpack<Apple[]> // => Apple
​
type Test = Unpack<Apple> // => Apple 

Partial

使用Partial将T中所有的属性都变为非必须的

用法
type Foo = {
  a: string
  b: number
  c: boolean
}
​
const a: MyPartial<Foo> = {} 
实现

1.首先使用 keyof T回 T 类型的所有键组成的一个联合类型 ,Foo类型则返回 string | number | boolean
2.使用in语法来遍历所有的key
3.将所有的属性改为非必须

type MyPartial<T> = {
  // 1. keyof T 会返回 T 类型的所有键组成的一个类型
  // 2. in 有点类似于 for...in 的语法。遍历所有的key[P in keyof T] ?: T[P]
} 

Required

将类型T中的所有属性都变为必须的

用法
type Foo = {
  a?: string
  b?: number
  c?: boolean
}
const a: MyRequired<Foo> = {}
// Erro
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值