Pull to refresh

Comments 3

Похоже на Merge из Type Fest

interface Foo {
	[x: string]: unknown;
	[x: number]: unknown;
	foo: string;
	bar: symbol;
}

type Bar = {
	[x: number]: number;
	[x: symbol]: unknown;
	bar: Date;
	baz: boolean;
};

export type FooBar = Merge<Foo, Bar>;
// => {
// 	[x: string]: unknown;
// 	[x: number]: number;
// 	[x: symbol]: unknown;
// 	foo: string;
// 	bar: Date;
// 	baz: boolean;
// }

Цикл по кортежу, увы, неправильный, там для [A, B, C, D] получается Extend<A, B> & Extend<B, D>, а для [A, B, C] вообще С проигнорируется. Надо поштучно:

type ExtendType<A extends unknown[], R = unknown> = A extends [infer F, ...infer T]
    ? ExtendType<T, Omit<R, keyof F> & F>
    : R;

Ну и надо заметить, что это именно extend, а не merge, то есть не всегда то, что может получиться в результате Object.assign({}, a, b, c) или {...a, ...b, ...c}, там всё более хитро, если дело касается опциональных ключей или ключей-индексов.

Вышеупомянутый Merge из type-fest тоже по факту работает как extend, но с некоторыми отличиями и менее правильно, например Merge<{a: number}, {[p: string]: boolean;}> оставляет ключ "a", хотя все ключи надо заменить на boolean

Более правильно или менее правильно зависит от желаемого поведения.

Если есть необходимость в другом поведении, просто можно добавить эту функциональсноть в TypeFest.

Sign up to leave a comment.

Articles