我下面有一个DeepMerge<>
通用名称,不支持深度的可选合并。
type DeepMerge<T, U> = [T, U] extends [object, object] ?
{
[K in keyof (U & Pick<T, Exclude<keyof T, keyof U>>)]: (
K extends keyof U ? (
K extends keyof T ? DeepMerge<T[K], U[K]> : U[K]
) : (
K extends keyof T ? T[K] : never
)
)
} : U;
我有一个Person
和一个很深的可选address
。
type Person = {
name: string,
age: number,
address: {
line1: string,
line2: string | null | number,
zip: string | number,
address?: {
line1: string,
line2: string | null | number,
zip: string | number,
},
},
};
我想覆盖较深的address
并添加burger
。
type PersonOverwrites = {
address: {
pizzaDelivery: boolean,
address?: {
burger: boolean,
},
},
};
这里是在抱怨:
const person: DeepMerge<Person, PersonOverwrites> = {
name: 'Thomas',
age: 12,
address: {
line1: 'hi',
line2: 'hi',
zip: 'hi',
pizzaDelivery: true,
address: {
line1: 'hi',
line2: 'hi',
zip: 'hi',
burger: true,
},
},
};
它应该要求line1
,line2
,zip
,burger
。
键入'{line1:string;第2行:字符串; zip:字符串;汉堡:真实; }'不能分配给类型'{burger:boolean; }'。 对象文字只能指定已知的属性,而'line1'在类型'{burger:boolean; }'。
它应该支持{ line1: string; line2: string; zip: string; burger: true; }
,但是整个深层对象将被覆盖到{ burger: boolean; }
。
答案 0 :(得分:3)
嗯,我想这里的问题是keyof ({a: string} | undefined)
显示为never
,因此只要该属性是可选的,DeepMerge
就无法递归下去。可能还有其他方法可以解决此问题,但是首先,如何将T
和U
更改为自己的NonNullable
版本,其中NonNullable
是{{3} }
type NonNullable<T> = T extends null | undefined ? never : T;
让我们尝试一下:
type DeepMerge<_T, _U, T= NonNullable<_T>, U= NonNullable<_U>> =
[T, U] extends [object, object] ?
{
[K in keyof (U & Pick<T, Exclude<keyof T, keyof U>>)]: (
K extends keyof U ? (
K extends keyof T ? DeepMerge<T[K], U[K]> : U[K]
) : (
K extends keyof T ? T[K] : never
)
)
} : U;
行得通吗?推断person
的类型为
const person: {
address: {
pizzaDelivery: boolean;
address?: {
burger: boolean;
line1: string;
line2: string | number | null;
zip: string | number;
} | undefined;
line1: string;
line2: string | number | null;
zip: string | number;
};
name: string;
age: number;
}
编辑:您可能只想defined in the standard library,就像这样:
type DeepMerge<T, U> = T extends any ? U extends any ?
[T, U] extends [object, object] ?
{
[K in keyof (U & Pick<T, Exclude<keyof T, keyof U>>)]: (
K extends keyof U ? (
K extends keyof T ? DeepMerge<T[K], U[K]> : U[K]
) : (
K extends keyof T ? T[K] : never
)
)
} : U : never : never;
也许对您来说更好?
希望有帮助。祝你好运!