怎么在TypeScript类型中实现js的if/else逻辑

8.4.0 前言

其实我们在写Typescript类型体操的时候,很多时候我们需要把思维从js上面转化到ts上面。那么我们需要怎么将我们的 js 逻辑转化成 ts 的类型编程逻辑呢。这篇文章会带大家 用 比较 简单的方式实现并进行练习

8.4.1 怎么实现同一层级 的 if/else

例如下面伪代码

kotlin 复制代码
function IfElseFlat(t){
    if(t == "string"){
        return "这是string"
    }
     if(t == "object"){
        return "这是object"
    }
    if(t == "number"){
        return "这是object"
    }
    ...
    else{
        return "啥也不是"
    }
}

我们应该怎么将这段逻辑转化成ts呢。原理就是利用 ts 的 条件链来做

typescript 复制代码
type IfElseFlat<t> =
    t extends string ? "这是string": 
    t extends object ? "这是object":
    t extends number ? "这是number":
"啥也不是"
​
// 输出 "这是object"
type IfElseCase = IfElseFlat<{}>
// 输出 "这是number"
type IfElseCase2 = IfElseFlat<2>

注意为了可读性 ,大家都会有自己的规则。我的写法一般是一般是

ini 复制代码
type xxx = 
    条件1 ? 结果1 :
    条件2 ? 结果2 :
兜底数据

这样子来进行 if/else 的 运算

8.4.2 怎么实现嵌套层级 的 if/else

js中类似这样的代码

kotlin 复制代码
function IfElseFlat(t){
    if(t == "string"){
        if(t=="神奇的string"){
            return "神奇string"
        }
        return "这是string"
    }
    else{
        return "啥也不是"
    }
}

也就是说嵌套的if/else ,就是把条件语句嵌套一下。两层 嵌套的格式就是 ? ? : : 。三层嵌套就是 ? ? ? : : : ,格式是 ab的格式

typescript 复制代码
type IfElseDeep1<t> =
    t extends string ? 
        t extends "神奇string"?
        "很神奇的string":
    "这是string":
"啥也不是"
​
type IfElseCase = IfElseDeep1<"神奇string">

也就是说语句可以总结成这样

ini 复制代码
type xxx = 
    (
        条件1  ?
            (
                条件2 ? 
                结果2 :
            )
        结果1:
    )
兜底数据

这样子来进行 if/else 的 运算.最后注意一下嵌套下面的tab

8.4.3 简单讲一下 嵌套 + 平级下面的套路

我们实际的类型编程中很少单独 其实只要多练习就好了。我们可以在平时有意识的练习这一块。主要就是把我们的js转化成ts 的 类型编程

比如下面的伪代码

kotlin 复制代码
function IfElseFlat(t){
    if(t=="string"){
        if(t=="hello"){
            return "这是hello"
        }else{
            return "这不是hello"
        }
    }else if(t=="object"){
        return "这是object"
    }else{
        return "啥也不是"
    }
}

我们可以将他尝试着变成类型的方法。简单的讲一下关键点

  • 自上到下
  • 遇上嵌套的if 用 ( )包裹 ,同时注意 输入tab 保持代码的可读(代码块每嵌套一个层级增加一个tab)
  • 优先处理 ? : 在 : 后面的逻辑,然后处理 ? 和 :中间的逻辑

这里我们采用渐进的演示方法,来给朋友直观讲述咱们的代码是怎么转化的

  • step1:处理 if(t=="string")else 的逻辑

    typescript 复制代码
    type IfElseFlat<t> = 
    t extends string ?
        // 代码块
    : "啥也不是"
  • step2:处理 if(t=="string") 的主逻辑,里面是嵌套逻辑因此套上一层 ()

    typescript 复制代码
    type IfElseFlat<t> = 
    t extends string ?
        (
            t extends "hello" ?
            "这是hello":
            "这不是hello"
        )
    : "啥也不是"
  • step3:然后处理一下 else if(t=="object")的情况,这个东西是平级因此我们可以直接在

    arduino 复制代码
    : "啥也不是"

    的上一行写入我们的逻辑,最终的成果也就是

    typescript 复制代码
    type IfElseFlat<t> =
        t extends string ? 
            (
                t extends "hello" ?
                "这是hello":
                "这不是hello"
            )
        : 
        t extends object ? "这是object":
    "啥也不是"

8.4.4 总结一下格式

  • 平级if/else

    每一行都是 ? : + 兜底数据

    markdown 复制代码
        条件1 ? 结果1 :
        条件2 ? 结果2 :
    兜底数据
  • 嵌套

    每一行 都是 ?

    多行必然是 ? ? : : 这样的 a* b*格式的数据

    注意添加括号和空行

    ini 复制代码
    type xxx = 
        (
            条件1  ?
                (
                    条件2 ? 
                    结果2 :
                )
            结果1:
        )
    兜底数据
  • 嵌套 + 平级

    • 自上到下
    • 遇上嵌套的if 用 ( )包裹 ,同时注意 输入tab 保持代码的可读(代码块每嵌套一个层级增加一个tab)
    • 优先处理 ? : 在 : 后面的逻辑,然后处理 ? 和 :中间的逻辑

8.4.5 练习 | 如何用符号连接object多层级并且合并成联合类型

如果你真的搞懂了 文章讲的内容,可以试一下完成下面的练习

涉及的知识点有

  • 映射类型
  • if/else 逻辑转化(也叫做条件语句)
  • extends
  • 字面量类型

如果有哪一个知识点不懂,可以先查阅一下资料再来做

好的,我们开始出题。我目前有这样一个 数据。我需要把他的结构用联合类型表达出来

input

css 复制代码
let obj = {
    a:{
        b:{
            c:"ddd",
            d:5
        }
    },
    d:{
        e:""
    }
}

output

ini 复制代码
type result = "a.b.d" | "a.b.c" | "d.e"

各位可以先想一下,答案我放在下面,

typescript 复制代码
let obj = {
    a:{
        b:{
            c:"",
            d:""
        }
    },
    d:{
        e:""
    }
}
​
​
type Flatten<t,u extends any> = {
    [k in keyof t] : 
    t[k] extends object ?
        (
            u extends "" ? Flatten<t[k],`${string & k}`>
            : Flatten<t[k],`${string & u}.${string & k}`>
        ) :
    `${string & u}.${string & k}`
}[keyof t]
​
type flatcase = DeepShowType<Flatten<typeof obj,""> & {}>
let cd :flatcase= "a.b.c"

这里的难点在于用到了两个 嵌套的 extends

上面这个函数可能没有什么实际作用,下面我们来封装一个工程上有用的东西

8.4.6 练习 | 如何封装一个函数实现 取出 指定的格式

我目前有这样一个 数据。我需要传入 他的 type和它层级的数据然后返回当前层级的type

input

css 复制代码
let obj = {
    a:{
        b:{
            c:"ddd",
            d:5
        }
    },
    d:{
        e:""
    }
}

output

ini 复制代码
// 调用 getprop<typeof obj,"a.b"> 得到数据
/*
type test2 = {
    c: string;
    d: number;
}
*/
​
type test2 = PropType<typeof obj,"a.b">

各位可以先想一下,答案我放在下面

scala 复制代码
type PropType<t, path extends string> =
path extends keyof t 
    ? t[path] :
        path extends `${infer first}.${infer second}` ?
            (first extends keyof t ?
                PropType<t[first], second> :
            unknown
            ) :
        unknown 
​
​
let obj = {
    a:{
        b:{
            c:"ddd",
            d:5
        }
    },
    d:{
        e:""
    }
}
// type getprop<t,p extends string> = PropType<t,p>
type test2 = PropType<typeof obj,"a.b">

很明显这里有三层嵌套的层级,很aw。各位可以慢慢理解

相关推荐
光影少年23 分钟前
react和vue图片懒加载及实现原理
前端·vue.js·react.js
小仓桑28 分钟前
深入理解 JavaScript 中的 AbortController
前端·javascript
摸鱼也很难30 分钟前
解决 node.js 执行 npm下载 报无法执行脚本的错
前端·npm·node.js
换个名字不能让人发现我在摸鱼30 分钟前
裁剪保存的图片黑边问题
前端·javascript
PeterJXL33 分钟前
pnpm:包管理的新星,平替 npm 和 yarn
前端·npm·node.js·pnpm
小牛itbull34 分钟前
Mono Repository方案与ReactPress的PNPM实践
开发语言·前端·javascript·reactpress
黑色的糖果35 分钟前
vue2封装自定义插件并上传npm发布及使用
前端·npm·node.js
afabama37 分钟前
nvm 安装某个版本的node,缺少npm包
前端·npm·node.js
码喽哈哈哈1 小时前
day01
前端·javascript·html