Comments 3
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
Sign up to leave a comment.
TS Extend: полезная утилитарная функция для расширения type