generated at
Merge<F, S>
2つのrecordを引数に取って、mergeしたrecordを返す
型レベルのSpread演算子のようなやつ

使用例
ts
type Foo = { a: number; b: string; }; type Bar = { b: number; c: boolean; }; type A = Merge<Foo, Bar>; // { a: number; b: number; c: boolean; }


定義例
無難
ts
type Merge< F extends Record<string, unknown>, S extends Record<string, unknown>, > = { [K in keyof F | keyof S]: K extends keyof S ? S[K] // 後ろ側であるSを先に書く : K extends keyof F ? F[K] : never; };
MergeIntersections<T>と組み合わせた定義
ts
type Merge< F extends Record<string, unknown>, S extends Record<string, unknown>, > = MergeIntersections<Omit<F, keyof S> & S>;
ただintersectionするだけではだめ
ts
type Merge<..> = MergeIntersections<F & S>;
keyが競合した際にneverになるため挙動が変わる
ts
type Merge< F extends Record<string, unknown>, S extends Record<string, unknown>, R = Omit<F, keyof S> & S, > = { [K in keyof R]: R[K]; };





なぜかこうは書けない
ts
type Merge< F extends Record<string, unknown>, S extends Record<string, unknown> > = { [K in keyof F | keyof S]: K extends keyof S ? S[K] : F[K]; // ここでerrorになる };
K extends keyof S を満たさなかった時、 F[K] と書けるのは自然な様に思うができない
そのため、無駄に K extends keyof F の条件を追加する必要がある
これはたぶんコンパイラがそこまで賢くないから?