最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 记一些ts上费过时间的地方 - 掘金

    正文概述 掘金(用户2634471179972)   2021-10-26   561

    记录一些自己在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 : false
      
      type 坑点 = {
        [key: string]: 坑点
      } | string
      
      type 测试<T> = T extends 坑点 ? true : false
      type 这个是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
        : never
      
      type HandleEmpty<T extends any[], Data> = T['length'] extends 0 ? never : Data
      
      type 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
        : never
      
      type 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坑后,可以没事关注下版本更新带来的新特性(玩法)。

    起源地下载网 » 记一些ts上费过时间的地方 - 掘金

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元