typescript - 创建多个泛型类型的交集类型
问题描述
我一直在对可变参数类型和 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 列表并将它们结合在一起,以便支持任何数量。例如,可能会返回一个版本的东西O & Partial<P1 & P2 & P3 ... & P100>
。
如果可能的话,我想避免需要大量的函数重载来支持这一点,因为我可以继续编写增加长度的元组版本。
解决方案
我不能确定,因为我没有安装你正在使用的库,但也许你可以这样做:
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
(在上面的例子中,我把它变成了一个休息参数而不是一个元组;TypeScript 不会从数组文字中推断出元组类型,但它会从一个rest 参数。如果你需要一个数组文字,你需要断言或以其他方式诱使编译器将其解释为元组)。
此类型参数SA
是一个数组ThemedStyleAugmentationFn<any, any>
。然后类型函数PfromSA<SA>
使用条件类型中的类型推断来计算所需的P
类型交集SA
。并且 type 函数SAExtendsTProperly<SA>
做了类似的事情来确保每个元素ThemedStyleAugmentationFn<P, TA>
都有TA
正确的扩展T
(因为ThemedStyleAugmentationFn<P, TA>
在 中可能是不变的TA
,你不能只是确保SA extends ThemedStyleAugmentationFn<any, T>
;你必须遍历元组并获取TA
每个元素的 )。
这应该可以按您的意愿工作,但同样,如果没有更多自包含代码,我无法确定。
希望对您有所帮助。祝你好运。
推荐阅读
- spring - 如何让浏览器知道从spring服务器下载过程中发生了错误?
- metadata - Ag-grid 列定义和 `__metadata__` 属性
- react-native - 无法在 VS Code 的模拟器上运行我的应用程序
- jmeter - Jmeter beanshell采样器编写多行
- typescript - Angular 11如何获取子数组中的所有项目是否包含另一个给定数组中的项目
- python - Lambda 'ffprobe/avprobe 和 ffmpeg/avconv 未找到'上的 youtube_dl 错误。
- html - 在新选项卡中打开 PDF - Blazor
- spring-boot - Spring boot 和 opentelemetry:未实现:未知服务 opentelemetry.proto.collector.metrics.v1.MetricsService
- c# - MSChart,鼠标移动时在 Axe-Y2 上显示 Y 值
- amazon-s3 - DSS-S3 存储桶在基于时间的运行中红移-[Amazon](500310) 无效操作:清单文件中不存在强制 url