我一直在大量阅读TypeScript中的可变参数类型和一些新的元组内容,但是由于当前的语言功能,我无法确定我要完成的工作是否完全不可能。
有关API的确切问题,请参见此处:
export type Themed<T> = { theme: T };
export type ThemedStyleAugmentationFn<P, T> = (
allProps: Partial<P> & Themed<T>
) => string;
export function augmentComponent<
P,
TA extends T,
C extends keyof JSX.IntrinsicElements | React.ComponentType<any>,
T extends object,
O extends object = {},
A extends keyof any = never
>(
styledComponent: StyledComponent<C, T, O, A>,
styleAugmentation: ThemedStyleAugmentationFn<P, TA>
): StyledComponent<C, T, O & Partial<P>, A> {
const augmented = styled(styledComponent)`
${styleAugmentation}
`;
return augmented as StyledComponent<C, T, O & Partial<P>, A>;
}
export function multiAugment<
P1 extends {},
TA1 extends T,
P2 extends {},
TA2 extends T,
C extends keyof JSX.IntrinsicElements | React.ComponentType<any>,
T extends object,
O extends object = {},
A extends keyof any = never
>(
styledComponent: StyledComponent<C, T, O, A>,
styleAugmentations: [ThemedStyleAugmentationFn<P1, TA1>, ThemedStyleAugmentationFn<P2, TA2>]
): StyledComponent<C, T, O & Partial<P1 & P2>, A> {
const augmented = styled(styledComponent)`
${styleAugmentations}
`;
return augmented as StyledComponent<C, T, O & Partial<P1 & P2>, A>;
}
在augmentComponent
中,签名的重要部分在这里:O & Partial<P>
。
在multiAugment
中,它显式地包含两个ThemeStyleAugmentationFun
的元组,它在这里:O & Partial<P1 & P2>
我希望能够编写一个multiAugment版本,该版本可以获取AugmentationFn的任意列表并将它们合并在一起,从而可以支持任何arity。例如,可能会返回O & Partial<P1 & P2 & P3 ... & P100>
版本的内容。
我想避免(如果可能)需要大量的函数重载来支持这一点,因为我可以继续编写长度不断增加的Tupled版本。
答案 0 :(得分:4)
我不确定,因为我没有安装您正在使用的库,但是也许您可以执行以下操作:
type PfromSA<SA extends Array<ThemedStyleAugmentationFn<any, any>>>
= { [K in keyof SA]: SA[K] extends ThemedStyleAugmentationFn<infer P, any> ? (x: P) => void : never } extends
{ [k: number]: (x: infer P) => void } ? P : never;
type SAExtendsTProperly<SA extends Array<ThemedStyleAugmentationFn<any, any>>, T>
= { [K in keyof SA]: SA[K] extends ThemedStyleAugmentationFn<any, infer U> ? [U] extends [T] ? SA[K] : ThemedStyleAugmentationFn<any, T> : never }
export function multiAugment<
SA extends Array<ThemedStyleAugmentationFn<any, any>>,
C extends keyof JSX.IntrinsicElements | React.ComponentType<any>,
T extends object,
O extends object = {},
A extends keyof any = never
>(
styledComponent: StyledComponent<C, T, O, A>,
...styleAugmentations: SA & SAExtendsTProperly<SA, T>
): StyledComponent<C, T, O & Partial<PfromSA<SA>>, A> {
const augmented = styled(styledComponent)`
${styleAugmentations}
`;
return augmented as StyledComponent<C, T, O & Partial<PfromSA<SA>>, A>;
}
这个想法是,您为styleAugmentations
参数使用了generic rest parameter(在上面的示例中,我将其设置为rest参数而不是元组; TypeScript不会从数组文字中推断出元组类型,但会从rest参数推断出元组类型。如果您需要数组文字,则需要声明或以其他方式诱使编译器将其解释为元组。
此类型参数SA
是ThemedStyleAugmentationFn<any, any>
的数组。然后,类型函数PfromSA<SA>
使用type inference in conditional types从P
计算出所需的SA
类型的交集。类型函数SAExtendsTProperly<SA>
的作用类似于确保每个元素ThemedStyleAugmentationFn<P, TA>
的{{1}}正确扩展了TA
(因为T
在{{1 }},您不能仅仅确保ThemedStyleAugmentationFn<P, TA>
;您必须遍历元组并为每个元素抓住TA
。
此应该可以根据您的需要工作,但是再次,我不确定没有更多独立的代码。
希望对您有帮助。祝你好运。