如何处理条件泛型类型,该类型在未定义时具有值,但在未定义时不具有值,这是另一回事 [英] How to do a conditional generic type that has a value when it is undefined but not when it is undefined AND another thing

查看:0
本文介绍了如何处理条件泛型类型,该类型在未定义时具有值,但在未定义时不具有值,这是另一回事的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类型,如果我不给任何值,我想用any将对象键定义为可选

type OptionalData<T> = T extends undefined ? { data?: any } : { data: T };

export type DataObject<T = any> = {
  item?: string | null;
} & OptionalData<T>;

在我将泛型设置为something | undefined

之前,它工作正常
const data: DataObject<string | undefined> = { data: true }; // WRONG!
const data2: DataObject<string | number> = { data: true }; // CORRECT

由于我的泛型还可以扩展undefined,所以我获取的数据是可选的any

当它只能扩展undefined或更多时,是否可以说它只是可选的any

Playground

推荐答案

问题

您有以下类型:

type OptionalData<T> = T extends undefined ? { data?: any } : { data: T };

export type DataObject<T = any> = {
  item?: string | null;
} & OptionalData<T>;

当您将变量键入为DataObject且类型参数是类型(如string)和undefined的并集时,您希望Data属性被类型化为联合类型,但它却被类型化为any

const data: DataObject<string | undefined> = { data: ... }

// data.data should be typed as `string | undefined` however
// data.data is typed as `any`

发生了什么?

TypeScrip的条件类型文档在这里很有用。上面写着:

其中选中的类型是裸类型参数的条件类型称为分布条件类型。在实例化过程中,分布式条件类型自动分布在联合类型之上。例如,具有类型参数A | B | C for TT extends U ? X : Y的实例化被解析为(A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)

-Documentation on distributive conditional types

所以在您的情况下,它解析为

| (string extends undefined ? { data?: any } : { data: T })
| (undefined extends undefined ? { data?: any } : { data: T })

第一个条件解析为{ data: T },第二个条件解析为{ data?: any }。我相信联合类型将解析为最泛型的类型,因此该类型最终是{ data?: any }

解决方案

此处OptionalData已更新,可按预期运行:

type OptionalData<T> = [T] extends [undefined] ? { data?: any } : { data: T };

我们只是用方括号([])将Tundefined括起来,将它们转换为元组(或者从技术上讲是一元组,因为它只有一个元素)。这是demo

此操作为什么有效?

让我们再次回顾一下条件类型的文档,重点放在重要部分:

选中类型为裸类型参数的条件类型称为分布式条件类型。分布式条件类型在实例化期间自动分布在联合类型上

当我们将这些裸体类型转换为元组时,它们不再是裸体的。因为它们不再是裸体的,它们不再被分发。

这篇关于如何处理条件泛型类型,该类型在未定义时具有值,但在未定义时不具有值,这是另一回事的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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