Describe the bug
First off, thank you very much for your work on cva. I'm using compose
from the beta version of cva @1.0.0-beta.1
to merge two cva components; functionally it works as expected, but the resulting Type appears to be incorrect, thereby breaking VSCode autocomplete for the composed/merged cva component. I wrote my own Compose
type that appears to fix it (see further below).
To reproduce
const A = cva({
base: "A",
variants: {
style: {
primary: "primary-A"
}
}
});
const B = cva({
base: "B",
variants: {
style: {
primary: "primary-B",
secondary: "secondary-B",
}
}
});
const C = cva({
base: "C",
variants: {
style: {
tertiary: "tertiary-C",
}
}
});
const merged = compose(A, B, C);
merged({ style: }) // auto-complete doesn't show any options for `style`; should show `primary`, `secondary`, `tertiary`
I'm really not a TS expert, but with the help of good ol' ChatGPT I came up with this alternative Typing for compose
that seems to fix the issue:
type MergeVariantProps<Types extends any[]> = Types extends [infer First, ...infer Rest]
? First extends object
? Rest extends any[]
? {
[K in keyof First | keyof MergeVariantProps<Rest>]: K extends keyof First
? K extends keyof MergeVariantProps<Rest>
? First[K] | Exclude<MergeVariantProps<Rest>[K], First[K]>
: First[K]
: K extends keyof MergeVariantProps<Rest>
? MergeVariantProps<Rest>[K]
: never
}
: never
: never
: {};
export interface Compose {
<T extends any[]>(...components: T): (
props?: Partial<MergeVariantProps<{ [K in keyof T]: VariantProps<T[K]> }>> & CVAClassProp
) => string;
}
const myCompose = compose as Compose;
const merged = myCompose(A, B, C);
merged({ style: }) // auto-complete now shows `style` options `primary`, `secondary`, `tertiary`
Happy to get a PR going with these changes, but wanted to get your take on this and/or figure out if I'm missing something.
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too