如何键入可分配给第三个参数的两个参数的交集
How to type the intersection of two parameters to be assignable to third
我试图在 TypeScript 中表达一个现有的 API,它有一个函数可以将两个参数组合成与第三个参数相同的形状。到目前为止,我尝试输入它看起来像这样(简化):
type Difference<A, B> = Pick<A, Exclude<keyof A, keyof B>>
export const foo = <Props, A extends Difference<Props, B>, B extends Difference<Props, A>>(
props: Props,
a: A,
b: B,
): Props => ({ ...a, ...b }); // Type 'A & B' is not assignable to type 'Props'.
Props
是 A
和 B
应该组合成的所需形状。我的想法是缩小 A
以扩展它与 B
的差异,反之亦然,但它会产生评论中看到的错误,尽管它的行为似乎符合预期:
const props = { x: 1, y: 1 };
foo(props, { x: 1, z: 1 }, { y: 1 }); // Valid
foo(props, { x: 1 }, {}); // Error
foo(props, { x: 1, y: 1 }, {}); // Valid
我应该向 return 值添加一个 as unknown as Props
断言吗?
这是另一种方法,它可能会让函数的用户有点困惑,因为错误是在 props
输入上。但它确保如果交集不起作用则无法调用该函数。
A & B
因为 return 类型应该始终是 Props
的子类,所以这不应该成为问题(并导致编译器不抱怨)。
export const foo2 = <Props, A, B>(
props: A & B extends Props ? Props : never,
a: A,
b: B,
): A & B => ({ ...a, ...b });
const props = { x: 1, y: 1 };
foo2(props, { x: 1, z: 1 }, { y: 1 }); // Valid
foo2(props, { x: 1 }, {}); // Error
foo2(props, { x: 1, y: 1 }, {}); // Valid
foo2(props, {}, { x: 1, y: 1 }); // Valid
我试图在 TypeScript 中表达一个现有的 API,它有一个函数可以将两个参数组合成与第三个参数相同的形状。到目前为止,我尝试输入它看起来像这样(简化):
type Difference<A, B> = Pick<A, Exclude<keyof A, keyof B>>
export const foo = <Props, A extends Difference<Props, B>, B extends Difference<Props, A>>(
props: Props,
a: A,
b: B,
): Props => ({ ...a, ...b }); // Type 'A & B' is not assignable to type 'Props'.
Props
是 A
和 B
应该组合成的所需形状。我的想法是缩小 A
以扩展它与 B
的差异,反之亦然,但它会产生评论中看到的错误,尽管它的行为似乎符合预期:
const props = { x: 1, y: 1 };
foo(props, { x: 1, z: 1 }, { y: 1 }); // Valid
foo(props, { x: 1 }, {}); // Error
foo(props, { x: 1, y: 1 }, {}); // Valid
我应该向 return 值添加一个 as unknown as Props
断言吗?
这是另一种方法,它可能会让函数的用户有点困惑,因为错误是在 props
输入上。但它确保如果交集不起作用则无法调用该函数。
A & B
因为 return 类型应该始终是 Props
的子类,所以这不应该成为问题(并导致编译器不抱怨)。
export const foo2 = <Props, A, B>(
props: A & B extends Props ? Props : never,
a: A,
b: B,
): A & B => ({ ...a, ...b });
const props = { x: 1, y: 1 };
foo2(props, { x: 1, z: 1 }, { y: 1 }); // Valid
foo2(props, { x: 1 }, {}); // Error
foo2(props, { x: 1, y: 1 }, {}); // Valid
foo2(props, {}, { x: 1, y: 1 }); // Valid