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