Typescript中部分类型的并集可以';不要缩小字体

Typescript中部分类型的并集可以';不要缩小字体,typescript,union-types,Typescript,Union Types,我有一个union类型,它表示用户可以使用表单字段构造的一段数据。基本流程是,用户选择他们想要制作的东西,然后我展示适当的UI,当他们编辑表单字段时,我更新存储的对象。根据用户选择制作的对象类型,进行中对象表示为联合类型的部分化版本。有两种方法我想引用部分化类型,但都有问题 代码片段可以解释更多,但基本上,回调的签名和类型保护是我希望引用in-progress值的两种方式。在我提出的两种方案中,定义一个部分化的联合类型,其中一个用例无法编译 看起来变体一更准确,所以我很惊讶它不能正确编译。如果可

我有一个union类型,它表示用户可以使用表单字段构造的一段数据。基本流程是,用户选择他们想要制作的东西,然后我展示适当的UI,当他们编辑表单字段时,我更新存储的对象。根据用户选择制作的对象类型,进行中对象表示为联合类型的部分化版本。有两种方法我想引用部分化类型,但都有问题

代码片段可以解释更多,但基本上,回调的签名和类型保护是我希望引用in-progress值的两种方式。在我提出的两种方案中,定义一个部分化的联合类型,其中一个用例无法编译

看起来变体一更准确,所以我很惊讶它不能正确编译。如果可能的话,我希望避免强制转换,以便使此代码尽可能健壮,能够向联合类型添加更多成员

导出接口密钥{
类型:“键”;
键:字符串;
}
导出接口键值{
类型:“键值”;
键:字符串;
值:字符串;
}
导出类型或=键|键值;
导出类型公共=拾取;
导出常量公共={
toString:({type,key}:Common):字符串=>null,如有,
fromString:(s:string):Common=>null,
};
//用例1:当使用下面的变体1时,这不起作用。
常量回调:(v:PartialEither)=>void=null,如有;
回调(Common.fromString(“”);
//用例2:当使用下面的变体2时,这不起作用。
//这是有道理的,因为变量2的定义删除了“type”之间的关系
//以及相应的对象形状,因此类型缩小无法工作。
常量:PartialEither=null,如有;
if(任一.type==“键值”){
要么是价值;
}
//变体一
//将其注释掉并替换为变体2,以查看上面的错误更改。
//使用这个中间类型,所以我仍然可以依赖“type”作为
//PartialEither类型。
类型_PartialEither=Pick&Partial;
导出类型PartialKey=\u PartialEither;
导出类型PartialKeyValue=\u PartialEither;
导出类型PartialEither=PartialKey | PartialKeyValue;
//变体二
//取消对该变量的注释,将其替换为变量1,以查看错误的更改,如上所示。
//类型PartialEither=拾取和部分

我不太明白为什么编译器不理解您的
PartialEither
类型;像这样涉及交叉点和映射类型的间隙并不是史无前例的,比如。。。并不是说这正是问题所在。无论如何,我的直觉是,无论什么问题,都更像是TypeScript中的bug/设计限制,而不是代码中的问题。不确定是否存在涉及此问题的现有问题,或者是否希望打开一个问题


尽管如此,如果我想在这里继续,我会尝试将
PartialEither
转换为我能做到的最简单的类型。。。没有交点的对象类型的并集。一种方法是使用我调用的实用程序类型
Expand

type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
并查看IntelliSense中观察到的
PartialEither
类型现在是:

type PartialEither = {
    type: "key";
    key: string;
} | {
    type: "key-value";
    key: string;
    value?: string | undefined;
}
当你这样做的时候,你的错误就会消失。那将是我的建议


回到“这似乎是TypeScript中的错误或设计限制”主题:

请注意,编译器确实认为
PartialKey | PartialKeyValue
Expand
是可相互分配的类型,否则将出现以下错误:

type MutuallyAssignable<T extends U, U extends V, V = T> = true;
type Okay = MutuallyAssignable<PartialKey | PartialKeyValue, PartialEither>; // no error
类型MutuallyAssignable=true;
类型Okay=MutuallyAssignable;//无误
但是当涉及到为它们分配
Common
类型的值时,编译器对其中一个感到满意,而对另一个感到不安:

函数hmm(公共:公共){
设nope:PartialKey | PartialKeyValue=common;//错误
让yep:PartialEither=common;//好的

yep=nope;//好的,我对编译器为什么不理解您的
PartialEither
类型没有很好的理解;像这样涉及交集和映射类型的间隙并非史无前例的,比如……并不是说这正是问题所在。总之,我的直觉是,无论什么问题都更像是一个bug/TypeScript中的设计限制,而不是代码中的问题。不确定是否存在涉及此问题的现有问题,或者是否希望打开一个问题


尽管如此,如果我想在这里继续,我会尝试将
PartialEither
转换为我能做到的最简单的类型…一个没有交叉点的对象类型的并集。一种方法是使用我称之为
Expand
的实用程序类型:

type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
并查看IntelliSense中观察到的
PartialEither
类型现在是:

type PartialEither = {
    type: "key";
    key: string;
} | {
    type: "key-value";
    key: string;
    value?: string | undefined;
}
当你这样做的时候,你的错误就会消失。这就是我的建议


回到“这似乎是TypeScript中的错误或设计限制”主题:

请注意,编译器确实认为
PartialKey | PartialKeyValue
Expand
是可相互分配的类型,否则将出现以下错误:

type MutuallyAssignable<T extends U, U extends V, V = T> = true;
type Okay = MutuallyAssignable<PartialKey | PartialKeyValue, PartialEither>; // no error
类型MutuallyAssignable=true;
类型Okay=MutuallyAssignable;//无错误
但是当涉及到为它们分配
Common
类型的值时,编译器对其中一个感到满意,而对另一个感到不安:

函数hmm(公共:公共){
设nope:PartialKey | PartialKeyValue=common;//错误
让yep:PartialEither=common;//好的

yep=nope;//好的,您的解决方案也可以,谢谢!AFAICT这是一个新的编译器错误,所以我已经归档并引用了这个答案。您的解决方案可以,谢谢!AFAICT这是一个新的编译器错误,所以我归档并引用了这个答案。