您当前的位置:首页 > 网站建设 > javascript
| php | asp | css | H5 | javascript | Mysql | Dreamweaver | Delphi | 网站维护 | 帝国cms | React | 考试系统 | ajax | jQuery | 小程序 |

一些在TypeScript上费过时间的地方总结

51自学网 2022-02-21 13:37:55
  javascript

记录一些自己在ts上费过时间的地方。

(先吐个槽:stackoverflow是真的啥都有,百度是真的没法用)

as断言的兼容性误解,如"a" as "b"这种代码是不会报错的。

interface和type的不一致行为(初遇还以为自己写错类型,一脸懵逼的):

type Type = {  key: "value"}interface Interface {  key: "value"}type 似乎没差别都是true = Type extends Interface ? Type extends Interface ? true : false : falsetype 坑点 = {  [key: string]: 坑点} | stringtype 测试<T> = T extends 坑点 ? true : falsetype 这个是true = 测试<Type>type 这个是false = 测试<Interface>

github上官方有说明,是故意留这么个坑的。说是因为interface可扩展(同名自动合并),所以不便检测。

用泛型实现函数重载的效果时,在函数的实现中,会因泛型不具备具体约束,导致经常需要使用as强制断言。

//差不多这意思,下面的代码懒得实际测了🙃//fns是个函数索引表,TFns是索引表的const类型function 重载失败<T extends keyof TFns>(fn:T, params: Parameters<fns[T]>){    fns[fn](...params)//在实现中联合类型不会缩小,所以会报错    //错误应该像是 不能将方法1的参数传给方法2 这种}//但外部使用时,符合类型的语义也没啥事

扩展运算符并不符合直观感受: [...string[], number]这种类型在使用时是符合阅读时的直觉的(要求数组末尾是number元素),但是[...string[], null, ...object[], number]这种不行,不会按顺序来也不会报错。新版ts加了禁止连续解构的规则,这种类型直接不让写了。

其实这里有解决办法,但是写出来的类型简直没法看(几十行,包含大量extends充当类型的if判断),就不贴了 下面贴代码:

//需要的类型:[...number[], "middle-element", ...boolean[]] //上面的写法是无效的,只是示意下面的类型代码是干什么用的(实现上面示意的类型约束)type Elem = number | boolean | "middle-element";type Last<T extends any[]> = T extends [infer _]  ? never  : T extends [...infer _, infer Tl]  ? Tl  : nevertype HandleEmpty<T extends any[], Data> = T['length'] extends 0 ? never : Datatype Validation<Params extends any[], Cache extends Elem[] = []> =  Params extends []  ? Cache['length'] extends 0  ? never  : Cache  : Params extends [infer Fst, ...infer Rest]  ? Cache extends []  ? Fst extends number  ? HandleEmpty<Rest, Validation<Rest, [...Cache, Fst]>>  : never  : Fst extends number  ? Last<Cache> extends number  ? HandleEmpty<Rest, Validation<Rest, [...Cache, Fst]>>  : never  : Fst extends "middle-element"  ? Last<Cache> extends number  ? HandleEmpty<Rest, Validation<Rest, [...Cache, Fst]>>  : never  : "middle-element" extends Cache[number]  ? Fst extends boolean  ? Validation<Rest, [...Cache, Fst]>  : never  : never  : nevertype IsNever<T> = [T] extends [never] ? true : false;function check<  Params extends Elem[],  IsValid extends Validation<Params>>(...arr: IsNever<IsValid> extends true ? [never] : [...Params]) {  return arr}const 正常 = check(1, 'middle-element', false)const 报错 = check(false, "middle-element", 2)

进阶操作

对象名重映射:

//{ "new-a":any; "new-b":any }type 重映射 = {    [K in "a" | "b" as `new-${K}`]: any}

联合类型的拆分:用infer关键字可以实现对联合类型的拆分。

//"a1"|"b2"type 拆分成功<_Keys = keyof { a: 1, b: 2 }> = _Keys extends infer K ?    `${Extract<K, string>}${{ a: 1, b: 2 }[Extract<K, _Keys>]}`    : never//注意:(截止ts4.4.4)直接`keyof Obj extends infer K`无法分割联合类型,原因不明(懒得查😁)。//结果是"a1"|"a2"|"b1"|"b2"type 拆分失败 = keyof { a: 1, b: 2 } extends infer K ?    `${Extract<K, string>}${{ a: 1, b: 2 }[Extract<K, "a" | "b">]}`    : never

元组类型:

  • 实际(非类型)参数有时候需要通过as const明确定义为元组类型。
  • 元组类型可以通过元组["length"]获取准确的长度,而不是number。
  • 元组类型在通过泛型参数使用时,有时候需要通过加个[]|写成元组 extends []|any[]这种方式来避免被解析为普通的不定长数组类型。

递归类型:用...infer More可以实现对数组类型的递归。

type 转换器<T> = T extends string ? "str" : null//进去是个[string,number,string],出来就会是["str",null,"str"]type 递归<        输入源 extends any[],        内部的类型缓存 extends any[] = []    > = 输入源 extends [any, ...infer 剩余元素] ?        递归<剩余元素, [...内部的类型缓存, 转换器<输入源[0]>]>        : 输入源

零碎

  • &可以代替extends对type使用,interface除了可以合并同名的类型,其它的没啥差别了。
  • ts具有丰富的内建类型,挑几个例子:
    • ReturnType<函数类型>,获取函数类型的返回值的类型。
    • Uncapitalize<字符串>,将输入的字符串类型的首字母锁定为小写(其它还有首字母大写、全小写、全大写)。

新手建议去官网翻文档。

入了ts坑后,可以没事关注下版本更新带来的新特性(玩法)。

总结

到此这篇关于在TypeScript上费过时间的地方总结的文章就介绍到这了,更多相关ts费时间的地方内容请搜索51zixue.net以前的文章或继续浏览下面的相关文章希望大家以后多多支持51zixue.net!


下载地址:
基于JavaScript实现密码框验证信息
js中的函数嵌套和闭包详情
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。