百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Typescript 那些好用的技巧(typescript在线编译器)

toyiye 2024-08-19 01:06 6 浏览 0 评论

一年前刚接触 Typescript 的时候, 觉得它加大了代码工作量. 写一大堆东西.为了找某个类型东奔西跑, 引入第三库还经常报错.


然而现在的我想说: 真香.

我们经常吐槽别人代码可维护性特别低, 总是希望别人能够主动的写注释, 可是写注释却没有任何方式可以进行约束. 这下好了, 类型就是最好的注释, 用 Typescript, 可以大大提高代码的可维护性.



一. 如何处理第三方库类型相关问题



Typescipt 所提供的第三方库类型定义不仅约束我们的输入调用, 还能为我们提供文档. 现在, NPM 上的第三方类型定义种类繁多,很难保证类型定义是正确的. 也很难保证所有使用的第三方库都有类型定义.

那么, 在这个充满未知的过程中,如何才能正确使用TypeScript中的第三方库呢?


下面列举了四种常见的无法正常工作的场景以及对应的解决方法:

  • 库本身没有自带类型定义
  • 库本身没有类型定义, 也没有相关的@type
  • 类型声明库有误
  • 类型声明报错


1. 库本身没有自带类型定义

查找不到相关的库类型. 举个栗子


在初次将 react 改造支持 typescript 时, 想必很多人都会遇到 module.hot 报错. 此时只需要安装对应的类型库即可.

安装 @types/webpack-env


2. 库本身没有类型定义, 也没有相关的@type

那只能自己声明一个了. 随便举个栗子.

declare module "lodash"

我自己是一名从事了多年开发的web前端老程序员,目前辞职在做自己的web前端私人定制课程,今年年初我花了一个月整理了一份最适合2019年学习的web前端学习干货,各种框架都有整理,送给每一位前端小伙伴,想要获取的可以关注我的头条号并在后台私信我:前端,即可免费获取。

3. 类型声明库有误

  • 推动解决官方类型定义的问题, 提issue, pr
  • Import 后通过 extends 或者 merge 能力对原类型进行扩展
  • 忍受类型的丢失或不可靠性
  • 使用 // @ts-ignore 忽略


4. 类型声明报错

  • 在 compilerOptions 的添加"skipLibCheck": true, 曲线救国


二. 巧用类型收缩解决报错


下面列举了几种常见的解决方法:

  • 类型断言
  • 类型守卫 typeof in instanceof 字面量类型保护
  • 双重断言


1、 类型断言

类型断言可以明确的告诉 TypeScript 值的详细类型,

在某些场景, 我们非常确认它的类型, 即使与 typescript 推断出来的类型不一致. 那我们可以使用类型断言.

语法如下:

<类型>值

值 as 类型 

// 推荐使用这种语法. 因为<>容易跟泛型, react 中的语法起冲突

举个例子, 如下代码, padding 值可以是 string , 也可以是 number, 虽然在代码里面写了 Array(), 我们明确的知道, padding 会被parseint 转换成 number 类型, 但类型定义依然会报错.

function padLeft(value: string, padding: string | number) {

   // 报错: Operator '+' cannot be applied to

   // types 'string | number' and 'number'

   return Array(padding + 1).join(" ") + value;

}


解决方法, 使用类型断言. 告诉 typescript 这里我确认它是 number 类型, 忽略报错.

function padLeft(value: string, padding: string | number) {

   // 正常

   return Array(padding as number + 1).join(" ") + value;

}


但是如果有下面这种情况, 我们要写很多个 as 么?

function padLeft(value: string, padding: string | number) {

   console.log((padding as number) + 3);

   console.log((padding as number) + 2);

   console.log((padding as number) + 5);

   return Array((padding as number) + 1).join(' ') + value;

}

2、 类型守卫

类型守卫有以下几种方式, 简单的概括以下

  • typeof: 用于判断 "number","string","boolean"或 "symbol" 四种类型.
  • instanceof : 用于判断一个实例是否属于某个类
  • in: 用于判断一个属性/方法是否属于某个对象
  • 字面量类型保护


上面的例子中, 是 string | number 类型, 因此使用 typeof 来进行类型守卫. 例子如下:

function padLeft(value: string,padding: string | number) {

   if (typeof padding === 'number') {

       console.log(padding + 3); //正常

       console.log(padding + 2); //正常

       console.log(padding + 5); //正常

        //正常

       return Array(padding + 1).join(' ')value;

   }

   if (typeof padding === 'string') {

       return padding + value;

   }

}


相比较 类型断言 as , 省去了大量代码. 除了 typeof , 我们还有几种方式, 下面一一举例子.


  • instanceof :用于判断一个实例是否属于某个类
class Man {

   handsome = 'handsome';

}


class Woman {

   beautiful = 'beautiful';

}


function Human(arg: Man | Woman) {

   if (arg instanceof Man) {

       console.log(arg.handsome);

       console.log(arg.beautiful); // error

   } else {

       // 这一块中一定是 Woman

       console.log(arg.beautiful);

   }

}
  • in : 用于判断一个属性/方法是否属于某个对象
interface B {

   b: string;

}


interface A {

   a: string;

}


function foo(x: A | B) {

   if ('a' in x) {

       return x.a;

   }

   return x.b;

}
  • 字面量类型保护

有些场景, 使用 in, instanceof, typeof 太过麻烦. 这时候可以自己构造一个字面量类型.

type Man = {

   handsome: 'handsome';

   type: 'man';


};


type Woman = {

   beautiful: 'beautiful';

   type: 'woman';

};


function Human(arg: Man | Woman) {

   if (arg.type === 'man') {

       console.log(arg.handsome);

       console.log(arg.beautiful); // error

   } else {

       // 这一块中一定是 Woman

       console.log(arg.beautiful);

   }

}

3、双重断言

有些时候使用 as 也会报错,因为 as 断言的时候也不是毫无条件的. 它只有当S类型是T类型的子集,或者T类型是S类型的子集时,S能被成功断言成T.

所以面对这种情况, 只想暴力解决问题的情况, 可以使用双重断言.

function handler(event: Event) {

   const element = event as HTMLElement;

   // Error: 'Event' 和 'HTMLElement'

    中的任何一个都不能赋值给另外一个

}


如果你仍然想使用那个类型,你可以使用双重断言。首先断言成兼容所有类型的any

function handler(event: Event) {

   const element = (event as any) as HTMLElement;

    // 正常

}

三. 巧用 typescript 支持的 js 最新特性优化代码


1. 可选链 Optional Chining

let x = foo?.bar.baz();

typescript 中的实现如下:

var _a;

let x = (_a = foo) === null ||

_a === void 0 ? void 0 : _a.bar.baz();

利用这个特性, 我们可以省去写很多恶心的 a && a.b && a.b.c 这样的代码


2. 空值联合 Nullish Coalescing


let x = foo ?? '22';


typescript 中的实现如下:

let x = (foo !== null && foo !== void 0 ?

foo : '22');

四. 巧用高级类型灵活处理数据


typescript 提供了一些很不错的工具函数. 如下图


  • 类型索引

为了实现上面的工具函数, 我们需要先了解以下几个语法:

keyof : 获取类型上的 key 值

extends : 泛型里面的约束

T[K] : 获取对象 T 相应 K 的元素类型

type Partial<T> = {

   [P in keyof T]?: T[P]

}

在使用 props 的时候, 有时候全部属性都是可选的, 如果一个一个属性写 ? , 大量的重复动作. 这种时候可以直接使用 Partial<State>


Record 作为一个特别灵活的工具. 第一个泛型传入对象的key值, 第二个传入 对象的属性值.

type Record<K extends string, T> = {

   [P in K]: T;

}


我们看一下下面的这个对象, 你会怎么用 ts 声明它?

const AnimalMap = {

   cat: { name: '猫', title: 'cat' },

   dog: { name: '狗', title: 'dog' },

   frog: { name: '蛙', title: 'wa' },

};

此时用 Record 即可.

type AnimalType = 'cat' | 'dog' | 'frog';


interface AnimalDescription {

name: string, title: string

}


const AnimalMap:

Record<AnimalType, AnimalDescription> = {

   cat: { name: '猫', title: 'cat' },

   dog: { name: '狗', title: 'dog' },

   frog: { name: '蛙', title: 'wa' },

};


  • never, 构造条件类型

除了上面的几个语法. 我们还可以用 never , 构造条件类型来组合出更灵活的类型定义.

语法:

never: 从未出现的值的类型


// 如果 T 是 U 的子类型的话,那么就会返回 X,否则返回 Y

构造条件类型 : T extends U ? X : Y
ype Exclude<T, U> = T extends U ? never : T;

// 相当于: type A = 'a'

type A = Exclude<'x' | 'a', 'x' | 'y' | 'z'>


  • 更简洁的修饰符: - 与 +

可以直接去除 ? 将所有对象属性变成必传内容.

type Required<T> = { [P in keyof T]-?: T[P] };


// Remove readonly

type MutableRequired<T> = {

    -readonly [P in keyof T]: T[P]

};  
  • infer: 在 extends 条件语句中待推断的类型变量。
// 需要获取到 Promise 类型里蕴含的值

type PromiseVal<P> =

P extendsPromise<infer INNER> ? INNER : P;


type PStr = Promise<string>;


// Test === string

type Test = PromiseVal<PStr>;


五. 辨别 type & interface


在各大类型库中, 会看到形形色色的 type 和 interface . 然而很多人在实际中却不知道它们的区别.


官网的定义如下:


An interface can be named in an extends or implements clause, but a type alias for an object type literal cannot.


An interface can have multiple merged declarations, but a type alias for an object type literal cannot.


从一张图看出它们两的区别:



建议: 能用 interface 实现,就用 interface , 如果不能才用 type.

原文链接:https://mp.weixin.qq.com/s/Y2-huY7uKu_GgWztAWcDug
作者:前端迷

相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码