Merge<F, S>
2つのrecordを引数に取って、mergeしたrecordを返す
使用例
tstype Foo = {
a: number;
b: string;
};
type Bar = {
b: number;
c: boolean;
};
type A = Merge<Foo, Bar>; // { a: number; b: number; c: boolean; }
定義例
無難
tstype 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;
};
tstype Merge<
F extends Record<string, unknown>,
S extends Record<string, unknown>,
> = MergeIntersections<Omit<F, keyof S> & S>;
ただintersectionするだけではだめ
tstype Merge<..> = MergeIntersections<F & S>;
keyが競合した際にneverになるため挙動が変わる
tstype Merge<
F extends Record<string, unknown>,
S extends Record<string, unknown>,
R = Omit<F, keyof S> & S,
> = {
[K in keyof R]: R[K];
};
なぜかこうは書けない
tstype 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
の条件を追加する必要がある
これはたぶんコンパイラがそこまで賢くないから?