我看谁还不会这几个 TypeScript 高级技巧

typescript 作为前端使用最多的框架之一,快来看看下面这些隐藏的高级技巧吧

Mapped Types

当我们在声明类型的时候,可以借助 Mapped Types 的方式对基础类进行扩展,这样就可以减少定义重复的基础类型

type Ev = {add: string;remove: string;move: string;
}type OnEvents = {[k in keyof Ev as `on${Capitalize<Exclude<k, 'move'>>}`]: () => void
}const userActions: OnEvents = {onAdd: () => { },onRemove: () => { },
}

上面的类型声明利用了 keyof 对原始的 基础类型 Ev 进行遍历形成行的 OnEvents 类型,这个类型的 key 的成员就是 Ev 类型中的 基础类型,同时这里使用了 as 对 重新的 map 的类型进行新的定义

as `on${Capitalize<Exclude<k, 'move'>>}`

我们可以将 key 的声明单独拎出来看,上面使用了 Excludemove 字段排除,并且通过 Capitalize 工具类将剩余的 key 转换成 onAddonRemove

Template literals

Template literals 模板字面类型通过 模板字符串语法,借以字符串字面类型为基础,并能通过联合扩展到许多字符串

type GapType = "margin" | "padding"
type GapDirection = "top" | "right" | "bottom" | "left"type GapCss = `${GapType}-${GapDirection}`

type SizeType = 'rem' | 'px' | '%';
type SizeCss = `${number}${SizeType}`
type MarginPadding = {[Key in GapCss]?: SizeCss
}
const margin: MarginPadding = {'margin-left': '1rem'
}

Never type

Never Type 类型表示的是那些永不存在的值的类型。它是任何类型的子类型,但没有类型是 never 的子类型(除了 never 本身)。never 类型常用于表示不可能发生的事情,例如一个函数永远不会正常返回,或者一个变量将永远不会有值.

type NoEmptyString<T> = T extends '' ? never : T;function failOnEmptyString<T extends string>(input: NoEmptyString<T>) {if (!input.length) {throw new Error('input is empty');}
}failOnEmptyString('');

所以上面的案例通过 never 类型进行限定,表示 failOnEmptyString 函数永远不能输入空的字符串

satisfies 操作符

satisfies 在 Typescript 4.9+ 版本才支持

TypeScript 中的 satisfies 操作符用于断言特定对象满足特定类型。这与使用类型断言(如 as)不同,因为 satisfies 不会改变变量的类型;它只是检查变量是否与指定类型兼容。如果类型检查失败,代码将无法编译,因此它是一种编译时特性。

type Colors = "red" | "green" | "blue";type RGB = [red: number, green: number, blue: number];const palette: Record<Colors, string | RGB> = {red: [255, 0, 0],green: "#00ff00",blue: [0, 0, 255]
};const red = palette.red.find(v => v === 255)

相信上面的报错在日常开发中,经常会遇到的,平常的解决方法大多数都是 使用 as 大法, 但是有时候 as 大法也不是很好用。 用 satisfies 就可以很好解决这种情况

const palette = {red: [255, 0, 0],green: "#00ff00",blue: [0, 0, 255]
} satisfies Record<Colors, string | RGB>;

infer

在 TypeScript 中,"infer"关键字是一个强大的功能,可用于Conditional Types条件类型的上下文中,根据使用它们的上下文自动推断类型。这可以使类型实用程序更加灵活,能够处理复杂的类型场景,而无需用户进行显式类型声明。

type ReturnType<T> = T extends (...args: any[]) => infer P ? P : any;

infer 关键字必须使用在「条件类型的子句」,也就是 extends 后面 ? 前面的位置

infer 的一些使用场景

  • 推断对象的值类型
type ObjVal<T> = T extends { x: infer U; } ? U : never;
const a: ObjVal<{ x: string }> = '2323'
  • 推断函数的参数类型
type FuncParamType<T> = T extends (x: infer U) => any ? U : never;
let aa: FuncParamType<(age: number) => false> = 2432
let aa1: FuncParamType<(age: number) => false> = '2432'

  • 推断 Generice 参数的类型
type PromiseType<T> = T extends Promise<infer U> ? U : never;
let b: PromiseType<Promise<boolean>> = false
let bb: PromiseType<boolean> = false

  • 推断 String 的一部分
type RemoveUnderscore<T> = T extends `_${infer R}` ? R : T;
let cc: RemoveUnderscore<number> = 2323
let cc1: RemoveUnderscore<string> = `_I have underscore`

只有以 _ 开头的字符串才会被推断成 R 类型

Type Guard 类型守卫

TypeScript 中,类型守卫(Type Guards)是一种技术或模式,它使你能够在编译时期确定一个变量的类型。这种机制对于在运行时根据不同的类型执行不同的操作非常有用,尤其是在处理联合类型或更复杂的类型结构时。

在 TS 中,我们可以使用 typeofinstanceOfis 等操作符来定义类型守卫

typeof

function padLeft(value: string | string[], padding: string | number) {if (typeof padding === "number") {return Array(padding + 1).join(" ") + value;}if (typeof padding === "string") {return padding + value;}throw new Error(`Expected string or number, got '${padding}'.`);
}console.log(padLeft("Hello, world", 4));
console.log(padLeft("Hello, world", "John says "));

instanceOf

class Bird {fly() {}
}class Fish {swim() {}
}function move(pet: Bird | Fish) {if (pet instanceof Bird) {pet.fly();} else if (pet instanceof Fish) {pet.swim();}
}const myBird = new Bird();
const myFish = new Fish();move(myBird);
move(myFish);

is

利用类型谓词 parameter is Type 来确定变量的类型

interface Bird {fly(): void;layEggs(): void;
}interface Fish {swim(): void;layEggs(): void;
}function isFish(pet: Bird | Fish): pet is Fish {return (pet as Fish).swim !== undefined;
}function getPetAction(pet: Bird | Fish) {if (isFish(pet)) {pet.swim();} else {pet.fly();}
}const pet = getPetAction({ fly: () => console.log("fly"), layEggs: () => console.log("egg") });

由于篇幅有限,关注小编,获取后续更多关于 typescript 使用技巧

如果觉得文章不错的话,帮忙点一个赞 👍 吧, 感谢

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/640591.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day_8题解

利用最大公约数求最小公倍数 #include<iostream> using namespace std;int gcd(int a,int b) {return b?gcd(b,a%b):a; }int main() {long long a,b;cin>>a>>b;long long ansgcd(a,b);cout<<(a*b)/ans<<endl;return 0; }排序遍历&#xff0c;记…

小游戏:贪吃蛇

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;贪吃蛇 &#x1f337;追光的人&#xff0c;终会万丈光芒 目录 &#x1f3dd;1.头文件&#xff1a; &#x1f3dd;2.实现文件&#xff1a; &#x1f3dd;3.测试文件 &#xff1a; 前言&#…

阿里云X魔搭社区Create@AI创客松第四届冠军:MumuLab

4月13日终于迎来了线下Demo Day&#xff0c;此前阿里云 X 魔搭社区 X Datawhale CreateAI创客松已经紧锣密鼓地准备了一个多月时间&#xff0c;全球150团队报名、创作出66作品、评选出25支团队进入决赛&#xff0c;作品范围覆盖从办公效率到法律调解再到游戏互动以及构建童话世…

【CSS】使用 scroll snap 实现页面的垂直大屏滚动

CSS 属性 scroll-snap-type 设置了在有滚动容器的情形下吸附至吸附点的严格程度。 scroll-snap-type 使用 scroll snap 也可以用于垂直滚动&#xff0c;全屏展示就是一个很好的例子: <main><section class"section section-1"></section><sect…

通过创新的MoE架构插件缓解大型语言模型的世界知识遗忘问题

在人工智能领域&#xff0c;大型语言模型&#xff08;LLM&#xff09;的微调是提升模型在特定任务上性能的关键步骤。然而&#xff0c;一个挑战在于&#xff0c;当引入大量微调数据时&#xff0c;模型可能会遗忘其在预训练阶段学到的世界知识&#xff0c;这被称为“世界知识遗忘…

Rust 使用结构体组织相关联的数据

目录 结构体的定义和实例化 使用字段初始化简写语法使用结构体更新语法从其他实例创建实例使用没有命名字段的元组结构体来创建不同的类型没有任何字段的类单元结构体结构体示例程序 通过派生 trait 增加实用功能方法语法 定义方法带有更多参数的方法关联函数多个 impl 块本文有…

7.Prism框架之对话框服务

文章目录 一. 目标二. 技能介绍① 什么是Dialog?② Prism中Dialog的实现方式③ Dialog使用案例一 (修改器)④ Dialog使用案例2(异常显示窗口) 一. 目标 1. 什么是Dialog?2. 传统的Dialog如何实现?3. Prism中Dialog实现方式4. 使用Dialog实现一个异常信息弹出框 二. 技能介…

微机原理实验三、将AX寄存器中的16位数分成4组,每组4位,让后把这四组数分别放在AL,BL,CL,DL

微机原理实验三、将AX寄存器中的16位数分成4组&#xff0c;每组4位&#xff0c;让后把这四组数分别放在AL,BL,CL,DL 功能&#xff1a; 将AX寄存器中的16位数分成4组&#xff0c;每组4位&#xff0c;让后把这四组数分别放在AL,BL,CL,DL ; 调试结果&#xff1a; input&#xff1a…

FoundationPose复现及Realsense应用

相关信息 标题 FoundationPose: Unified 6D Pose Estimation and Tracking of Novel Objects作者 Nvidia (Bowen Wen Wei Yang Jan Kautz Stan Birchfield)主页 https://nvlabs.github.io/FoundationPose/链接 https://arxiv.org/abs/2312.08344代码 https://github.com/NVlab…

C++设计模式:中介者模式(十五)

1、定义与动机 定义&#xff1a;用一个中介对象来封装&#xff08;封装变化&#xff09;一系列的对象交互。中介者使各个对象不需要显示的相互引用&#xff08;编译时依赖 -> 运行时依赖&#xff09;&#xff0c;从而使其耦合松散&#xff08;管理变化&#xff09;&#xff…

【数据库系列】NebulaGraph部署与使用

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

联想拯救者电脑数据恢复方法,适用于未备份者

自从大学时期起&#xff0c;我的联想拯救者电脑就成为了我生活和学习的得力助手&#xff0c;里面存有许多至关重要的资料。但是昨日当我启动它时&#xff0c;电脑却意外卡顿。恢复正常后&#xff0c;发现部分数据竟然神秘地消失了&#xff0c;有什么方法能帮我恢复吗&#xff1…