vanilla-extract
vanilla-extract copied to clipboard
Typescript can't resolve which overload to use in `createTheme()` which makes it so we don't have autocomplete.
Describe the bug
Typescript doesn't seem to resolve to the correct overload signature when calling createTheme()
:
// try this on the reproduction link
const vars = createThemeContract({
a: null,
b: null
});
const theme = createTheme(vars, {
// typescript doesn't give suggestions
})
I think its because typeof vars
can extend both Tokens
and Contract
, so typescript can't choose the correct overload from the first argument passed, so it relies on the second argument to distinguish them, but since both signatures throw an error at that part, the user's mistake can either be that the user didn't give the correct parameter of type "string" or the user supplied an object with missing/incorrect properties.
I'm guessing it doesn't give out suggestions for the second error because of the first one.
Possible solutions
This one can be done on the user's side. Create another function that just returns createTheme()
but will always expect two arguments, contract
and token
. This is a little tedious cause vanilla-extract doesn't export the internal types needed so I think the only way is to infer/copy those types somehow.
// imagine I infered the types correctly
function createThemeFrom<T extends Contract>(
contract: T,
tokens: MapLeafNodes<T, string>,
id?: string
) {
return createTheme(contract, tokens, id);
}
Another one just for the user is to steal the MapLeafNodes<T, Leaf>
utility and make your own:
type Theme<T> = MapLeafNodes<T, string>
// then use it like:
const vars = createThemeContract({ a: null, b: null });
const lightTheme: Theme<typeof vars> = {
// ...
}
const theme = createTheme(vars, lightTheme);
A weird but easy fix I found was to change the order of the function declarations, putting the contract one first. I'm guessing maybe when errors are raised from multiple overload matches, the "suggestions" default to the first declaration:
// simplified example:
type JustMaps<T> = { [K in keyof T]: T[K] };
declare function example<T>(t: T, obj: JustMaps<T>, id?: string): string
declare function example<T>(t: T, id?: string): void
const result = example({ a: '' }, {
// has autocomplete!
});
Reproduction
https://www.typescriptlang.org/play?ts=4.5.5#code/JYWwDg9gTgLgBAbzgYygUwIYzQFQBZohoA0K6WuBRAwhAHYxQbLwC+cAZlBCHAEQABAG4Y6wADbiMAWjQAPRsxgB6ZAGc1fANwAoHcnpr4IqGrgBeMpmz5CaWgyYsAFAh1wPcDAC44dAK6SxO6eAEa+AZI6rACUuvqG8DBUaBZWFLZEziZqpG6ecMrKcMlo6HDAZnQQXv4wEAbg4mjY0XF6OkVwaqBg4sAcwGgAJnDyGE1o3jowAJ5gqQBS-kYAshhgagA8OAB8aUgA2gDSFXRwANZosxAccDgAur44Jw9wrPHDaMhS5Rz+dBYwHoYzkEz6aB2u2cMGepGAwwA-L4jFBgHQAOYxXxCCAInRfH4YP4AoEg8aTKEwuFwCChABWvmWaw22z28KRKMY6KxXLRmL0BjoRjg6DUgXglgpENcXl8AHJ5e88iEPF01BNUmBuKFmiA2vEugB3NDAKDDcSzEp4CD+DF4UjJSpwI3QC5qaaE36pf6AmDA87S5oAJipsPupDpjLgzJg602UI5yO63Mx2JT-IxBO+3s4pP95LBk1De2pEYqnIzPPTuPxCWF8FdUAuPLSQbQwdlPjgiuViFVhWKeAwZgwdQaPAh2AAhAagA
System Info
N/A
Used Package Manager
npm
Logs
No response
Validations
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] The provided reproduction is a minimal reproducible example of the bug.
Another one just for the user is to steal the MapLeafNodes<T, Leaf> utility and make your own
This can also be done like this:
const vars = createThemeContract({ a: null, b: null });
type Vars = Parameters<typeof createTheme<typeof vars>>[1];
const lightTheme: Vars = {
// ...
}
const theme = createTheme(vars, lightTheme);