检查联合体类型 [英] Checking for union type

查看:72
本文介绍了检查联合体类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种将联合类型作为函数参数的方法,然后能够使用这些参数,所有丢失的参数都将是未定义的

I am looking for a way to have union types as function arguments, then be able to use the arguments, any missing arguments would be undefined

但是在这里,姓名和年龄引起类型问题.

However here, name and age are causing a type issue.

function example(props: { id: number } & ({ name: string } | { age: number })) { 
  const { id, name, age } = props
}

这就是我想要的:

example({ id: 1, name: "Tom" })

example({ id: 1, age: 31 })

推荐答案

找到了 StrictUnion 的一小部分

A small variation of StrictUnion found here will work well:

type UnionKeys<T> = T extends T? keyof T : never;
type StrictUnionHelper<T, TAll> = T extends T? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, undefined>> : never;
type StrictUnion<T> = StrictUnionHelper<T, T>

function example(props: StrictUnion<{ id: number } & ({ name: string } | { age: number })>) { 
  const { id, name, age } = props
}

游乐场链接

StrictUnion 的工作方式是,确保工会的所有组成部分都拥有工会所有组成部分的所有成员.它通过添加所有类型为 undefined 的缺少的成员来确保这一点.因此,此类型为: {id:number}&({名称:字符串} | {年龄:数字})将变为以下类型: {id:number;名称:字符串;年龄:未定义} |{ 身份证号码;名称:未定义;年龄:数字} .由于这种新类型具有相同的结构,因此我们可以对其进行解构.

The way StrictUnion works is by ensuring all constituents of the union have all members from all the constituents of the union. It ensures this by adding any members that are missing with the type undefined. So this type: { id: number } & ({ name: string } | { age: number }) will become this type: { id: number; name: string; age: undefined } | { id: number; name: undefined; age: number }. Since this new type has the same structure we can de-structure it.

要构建 StrictUnion ,我们必须首先从所有联合组成部分获得所有键的联合.为此,我们必须使用分配行为条件类型.使用此行为,我们可以构建一个类型,该类型提取将提取每个并集组成部分的键并创建所有并集.为了触发分配行为,我们可以使用始终为真的条件( T扩展T T扩展未知,或者不太理想的 T扩展任何).这样,我们得出以下类型来提取所有键:

To build StrictUnion we must first get a union of all the keys from all union constituents. To do this we must use the distributive behavior of conditional types. Using this behavior we can build a type that extracts extracts the keys of each union constituent and creates a union of all. To trigger the distributive behavior we can use an always true condition ( T extends T, T extends unknown or, less ideal T extends any). With this we arrive at the following type extract all the keys:

type UnionKeys<T> = T extends T ? keyof T : never;

下面我们可以看到这种类型的应用方式:

Below we can see how this type is applied:

type A = { id: number; name: string }
type B = { id: number; age: number }

UnionKeys<A | B>
  // Conditional type is applied to A and B and the result unioned
  <=> (A extends unknown ? keyof A: never) | (B extends unknown ? keyof B: never) 
  <=> keyof A | keyof B
  <=> ("id" | "name") | ("id" | "age")
  <=> "id" | "name" | "age"

有了 UnionKeys 之后,我们可以使用另一种分布式条件类型遍历每个并集成员,并查看给定类型 T 中缺少哪些键(使用排除< UnionKeys< TAll>,T的键),然后将原始的 T 与包含这些内容的 Partial Record 相交键入 undefined 的键.我们需要将并集两次传递给分布类型,一次要通过( T )进行分配,一次要使整个联合能够使用 UnionKeys 提取键

After we have UnionKeys we can use another distributive conditional type to go through each of the union members and see what keys are missing from a given type T (using Exclude<UnionKeys<TAll>, keyof T>) and intersecting the original T with a Partial Record that contains these keys typed as undefined. We need to pass the union to the distributive type twice, once to distribute over (T), and once to have the whole union to be able to extract the keys using UnionKeys.

下面我们将看到如何应用此类型:

Below we ca see how this type is applied:

type A = { id: number; name: string }
type B = { id: number; age: number }
StrictUnion<A | B>
  <=> StrictUnionHelper <A | B, A | B>
  // Distributes over T
  <=> (A extends A ? A & Partial<Record<Exclude<UnionKeys<A | B>, keyof A>, undefined>> : never) | (B extends B ? B & Partial<Record<Exclude<UnionKeys<A | B>, keyof B>, undefined>> : never)
  <=> (A extends A ? A & Partial<Record<Exclude<"id" | "name" | "age", "id" | "name">, undefined>> : never) | (B extends B ? B & Partial<Record<Exclude<"id" | "name" | "age", "id" | "age">, undefined>> : never)
  <=> (A extends A ? A & Partial<Record<"age", undefined>> : never) | (B extends B ? B & Partial < Record < "name" >, undefined >> : never)
  // The condition A extends A and B extends B are true and thus the conditional type can be decided
  <=> (A & Partial<Record<"age", undefined>>) | (B & Partial<Record<"name">, undefined>>)
  <=> { id: number; name: string; age?: undefined } | { id: number; age: number; name?: undefined }

这篇关于检查联合体类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆