怎么在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。各位可以慢慢理解

相关推荐
赵庆明老师2 分钟前
vben开发入门5:vite.config.ts
前端·html·vue3·vben
qq_12084093712 分钟前
Three.js 工程向:实例化渲染 InstancedMesh 的批量优化
前端·javascript
起这个名字7 分钟前
LangGraphJs 核心概念、工作流程理解及应用
前端·人工智能
小赵同学WoW7 分钟前
vue组件基础知识
前端
牛奶16 分钟前
浏览器藏了这么多神器,你居然不知道?
前端·chrome·api
WebInfra21 分钟前
Rspack 2.0 正式发布!
前端·javascript·前端框架
极速蜗牛28 分钟前
Cursor最近变傻了?
前端
码字小学妹38 分钟前
Claude Opus 4.7 接入指南(2026):国内配置 + xhigh 推理 + 成本计算
前端
小赵同学WoW40 分钟前
插槽【vue2】与 【vue3】对比
前端
代码随想录40 分钟前
Agent大厂面试题汇总:ReAct、Function Calling、MCP、RAG高频问题
前端·react.js·前端框架