TypeScript 协变与逆变转换联合类型为交叉类型

最近在搬砖的时候,遇到一个场景,需要根据已存在的联合类型,将其转为交叉类型:

type Preson = {
     
  name: string
} | {
   
  age: number
} | {
   
  needMoney: boolean
}

type Result = Uinon2Intersection<Preson>

期望通过 Uinon2Intersection 转换后,得到的 Result

type Result = {
     
  name: string
} & {
   
  age: number
} & {
   
  needMoney: boolean
}

刚开始感觉很简单。我想已经会了类型体操基本动作四件套了。通过遍历联合类型,然后遍历的时候通过 key 读取属性值就行了,我啪啪啪就写出来了,就像这样:

type U2I<T> = {
   
  [key in keyof T]: T[key]
}

type Result = U2I<Preson>

实际得到的是:

type Result = U2I<{
   
    name: string;
}> | U2I<{
   
    age: number;
}> | U2I<{
   
    needMoney: boolean;
}>

Nmmm,这完全不是我期望的样子啊,然后又想了想基础四件套,感觉遇到坑了,好像仅靠四件套并不能解决啊。

先说下,上面这种情况是因为**对于联合类型,在遍历操作或者进行条件类型判断的时候,会发生类型分配**。就像下面:

type ToArray<Type> = Type extends any ? Type[] : never;

type StrArrOrNumArr = ToArray<string | number>;

其实得到:

type StrArrOrNumArr = string[] | number[]

如果想得到: (string | number)[]。你需要这么写:

type ToArrayNonDist<Type> = [Type] extends [any] ? Type[] : never;

回到正文,如果说我们想通过一个工具类型实现联合类型到交叉类型的转换,那需要了解一下下面几个 ts 关键概念:协变、逆变、双向协变、不变性。

类型兼容与可替代性

我们先说说类型兼容与可替代性,因为这两个概念与协变、逆变密切相关。

Typescript 的类型兼容特性是基于类型结构的,其基本规则是:如果 y 类型至少有一些与 x 类型相同的成员,则 x 类型与 y 类型兼容

例如,设想一个名为 Pet 的接口的代码,该接口有一个 name 属性;一个名为 Dog 的接口,该接口有 name

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值