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

记录一些自己在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坑后,可以没事关注下版本更新带来的新特性(玩法)。

总结

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

(0)

相关推荐

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

    记录一些自己在ts上费过时间的地方. (先吐个槽:stackoverflow是真的啥都有,百度是真的没法用) 坑 as断言的兼容性误解,如"a" as "b"这种代码是不会报错的. interface和type的不一致行为(初遇还以为自己写错类型,一脸懵逼的): type Type = { key: "value" } interface Interface { key: "value" } type 似乎没差别都是true

  • js实现在网页上简单显示时间的方法

    本文实例讲述了js实现在网页上简单显示时间的方法.分享给大家供大家参考.具体如下: 这是一款网页时钟JS代码,纯javascript实现,显示时.分.秒.网页时间显示.网页时钟有很多,这个真的挺简易的,美工好的朋友可在此基础上进一步美化完善 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-tr

  • javascript页面上使用动态时间具体实现

    复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv=&qu

  • python 时间 T 去掉 带上ms 毫秒 时间格式的操作

    我就废话不多说了,大家还是直接看代码吧~ import datetime # 时间格式 .%f 毫秒 ## "%Y-%m-%dT%H:%M:%S.%f" # 格式 秒 ## "%Y-%m-%dT%H:%M:%S" # 格式 分钟 ## "%Y-%m-%dT%H:%M" # 将 字符串格式的时间,转成时间毫秒格式 update_time = datetime.datetime.strptime(i["UpdatedAt"][:2

  • Java从服务器上获取时间动态显示在jsp页面实现思路

    Java获取服务器时间,动态显示到jsp页面,大家都是到Java只能获取一次,到页面的时间是静态的,不过通过js和Java的合作,巧妙地实现此功能. 本人是给电视做系统,客户要求页面能显示时间,因为电视浏览器获取的时间不对,没办法只能从服务器获取时间,但是问题来了,服务器的时间获取一次就成静态的了,客户不满意,但也没办法,只能这样.不过这个问题在我这老惦记着,今天看到有个例子,说把Java获取服务器的时间转化成毫秒,然后用js每一秒刷新一次就可以动态显示,所以就有了下面的 复制代码 代码如下:

  • 7个好用的TypeScript新功能

    1. 可选链 从 v3.7 可用 这是当你尝试访问嵌套数据时的一个痛点,嵌套数据越多,代码就会变得越繁琐. 在下面的例子中,要访问address,你必须遍历data.customer.address,而且data或customer有可能是undefined,所以通常使用&&运算符或类似例子中的技巧遍历检查每个层次的定义. 现在你可以用.?运算符来选择性地对数据访问.通过这种方式,如果存在尚未定义的父级对象,则会在链中的任何位置返回未定义,而不是在运行时崩溃. // v3.7 以前 if (

  • 简单三行代码函数实现几十行Typescript类型推导

    目录 场景 摸鱼吃瓜式排查 元组大法 感叹 场景 最近在设计一些基础的项目框架设计上的 sdk api,比如埋点系统.权限系统之类的,要提供一些便捷的封装方法给上层使用.于是遇到了这么个场景. 有一个对象常量里,存了一些方法,例如: const METHODS = { a: () => "a" as const, b: () => "b" as const, c: () => "c" as const } 然后想要封装这样一个

  • Perl中的10个操作日期和时间的CPAN模块介绍

    能够操控日期和时间对于大多数编程语言来说是基本的能力,Perl也不例外.但是在碰到与时间相关的更加复杂的处理时,Perl自带的功能常常就显得力不从心了.在这种情况下,上Perl综合典藏网(CPAN)看看是一个好主意,上面有很多随时可以使用的Perl模块,让开发人员能够有效地进行日期和时间操作.花点时间浏览这个网站看看是否能够找到一些在下一个项目里用得上的东西是值得的. 本文列出了Perl CPAN上用来操控日期和时间的10个最有趣的模块,为您下一次转化时区和计算两个时间戳之间的秒数打下了基础,现

  • 抓住用户碎片时间推广 一天突破10000+流量

    随着人们的紧凑生活,从事互联网行业的人大多都把一天的时间安排的满满的,这用户忙碌的时候,根本无心去关注你的推广,只有抓住了用户零零碎碎的时间对其进行推广,同时他也能打发无聊的时间,这样的效果就非常轻松,下面,我结合案例来为大家分享一下,如何抓住用户碎片时间进行营销推广,一天轻松突破10000+流量,这样的流量对于SEO人员来说算是一笔巨大的财富吧. 一.用户的碎片时间分段分析 碎片时间就是用户除了忙碌时间都称为碎片时间,现代人的生活上个厕所都离不开手机,赶飞机也难免发生晚点,这类时间就称为碎片时

  • Struts2 文件上传进度条的实现实例代码

    最近在写我们大三项目的一个视频文件上传的页面,实现后台对上传的进度进行监听,然后将监听的信息返回给前台页面. 前台的页面效果图: 前台进度条控件选择使用easyui 的progressbar控件. 详细的使用说明参考官网文档:http://www.jeasyui.com/documentation/index.php 所有需要引入jquery-1.11.1.min.js 以及jquery.easyui.min.js 一.前台的代码: <%@ page language="java"

随机推荐