Typescript {foo:null}与类型{bar?:null;fnord?:null}没有共同的属性

Typescript {foo:null}与类型{bar?:null;fnord?:null}没有共同的属性,typescript,types,union-types,Typescript,Types,Union Types,我有一些类型,它们共享公共道具,但这些道具有不同的对象。我想合并这些子对象,但它没有按我所期望的方式工作。这是我的代码: interface IFoo { foo: any }; interface IBarFnord { bar?: any; fnord?: any }; type Union = {test: IFoo } & {test: IBarFnord; otherTest?: IBarFnord }; const fails: Union = { test: { foo

我有一些类型,它们共享公共道具,但这些道具有不同的对象。我想合并这些子对象,但它没有按我所期望的方式工作。这是我的代码:

interface IFoo { foo: any };
interface IBarFnord { bar?: any; fnord?: any };

type Union = {test: IFoo } & {test: IBarFnord; otherTest?: IBarFnord };

const fails: Union = { test: { foo: null }};
const works: Union = { test: {foo: null, bar: null }};
const alsoWorks: Union = { test: {foo: null, fnord: null }};
对于
const失败
我得到错误:

类型“{foo:null;}”与类型“IBarFnord”没有共同的属性

这是真的。如果Union means必须同时具有这两个属性,那么它是有意义的

我已经测试过这样做,但不是作为子计划,而且效果很好:

type Union = {test: IFoo & IBarFnord };

const worksNow: Union = { test: { foo: null }};
const stillWorks: Union = { test: {foo: null, bar: null }};

无论如何,我如何告诉Typescript我想合并这些东西,但我不希望每个项目在合并的两边都有道具?

假设你实际上指的是“交叉点”而不是“联合点”,这看起来像是一个分别适用于交叉点的每个组成部分的公式,当它实际上只应用于整个交叉口时。看起来最近有人做了一些事情来解决这个问题,所以也许有一个修复程序将使它成为一个即将发布的版本?不确定

无论如何,作为一种解决方法,我们可以创建自己的类型别名,该别名可以主动递归地合并交叉点类型中的子属性,如下所示:

type SubpropertyMerge<T> = T extends (...args: infer A) => infer R
  ? (...args: SubpropertyMerge<A>) => SubpropertyMerge<R>
  : T extends object ? { [K in keyof T]: SubpropertyMerge<T[K]> } : T;
但是现在你的作业应该按照你的预期进行:

const worksNow: MergedIntersection = { test: { foo: null } };
好吧,希望这会有帮助;祝你好运


您使用的是单词,但您使用的是
&
,表示。这些是不同的;你到底想要哪一个?
typeunion=subpertymerge
成功了!
type MergedIntersection = SubpropertyMerge<Intersection>;
type IntersectionIsOkay = MutuallyExtends<Intersection, MergedIntersection>; // acts the same
const worksNow: MergedIntersection = { test: { foo: null } };