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的逻辑typescripttype IfElseFlat<t> = t extends string ? // 代码块 : "啥也不是" - 
step2:处理
if(t=="string")的主逻辑,里面是嵌套逻辑因此套上一层 ()typescripttype IfElseFlat<t> = t extends string ? ( t extends "hello" ? "这是hello": "这不是hello" ) : "啥也不是" - 
step3:然后处理一下
else if(t=="object")的情况,这个东西是平级因此我们可以直接在arduino: "啥也不是"的上一行写入我们的逻辑,最终的成果也就是
typescripttype 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*格式的数据
注意添加括号和空行
initype 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。各位可以慢慢理解
