vite-plugin-solid
vite-plugin-solid copied to clipboard
I updated `vite-plugin-solid` and now namespaces merged with components are no longer allowed
Describe the bug
If I create a .tsx
file with this content
function A() {
return <>1</>
}
namespace A {
export const a = 1;
}
console.log(A);
It throws this error when I load the page (Running vite dev
)
Transform failed with 1 error:
ERROR: The symbol "A" has already been declared
I tried downgrading vite-plugin-solid
and it worked
npm i [email protected]
(On the playground it always works)
Your Example Website or App
(localhost)
Steps to Reproduce the Bug or Issue
- Put a merged namespace declaration WITH A COMPONENT somewhere
- Run
vite dev
- Go to the web page
Expected behavior
I expected this allowed TS syntax to not stop working
Screenshots or Videos
No response
Platform
- OS: Windows
- Browser: Edge
- Version: 120.0.2210.77
Additional context
No response
Okay so it seems that namespace A
is actually A = {...}
(an assignment, rather than a declaration).
It's a very weird edge case honestly, although I would've expected it to raise an error too if not for functions to be re-assignable, and if namespaces transformed into variable declarations. Not sure if this should be fixed.
Besides assignment to function A
was there any other case where a namespace of similar name is desirable?
update:
Upon checking, since we convert every function component into a HOC (declared via a variable), it seems that TS compiles weirdly for it.
Example:
const A = () => {
};
namespace A {
export const hello = 'world';
}
const A = () => {
};
var A;
(function (A) {
A.hello = 'world';
})(A || (A = {}));
and since we rely on HOC to apply HMR, this is most likely a wontfix. However, I would recommend just assigning to the function directly.
related: https://github.com/microsoft/TypeScript/issues/51417
Isn't it possible to use var
?
var A = () => {
};
var A;
(function (A) {
A.hello = 'world';
})(A || (A = {}));
@AFatNiBBa your example code shows why it won't work.
Do you transform the function to make HMR work BEFORE or AFTER transpiling typescript?
Because if you were to do it after you could declare the function with var
// ↓
export var A = _$$component(_REGISTRY, "A", function A() {
// ...
}, {
location: "..."
});
And if you're doing it before the transpiling because if you were to do it after you would not know where the JSX was, then you could mark the function in some way (Maybe with a comment?) in order to still find it at the end
@AFatNiBBa
Do you transform the function to make HMR work BEFORE or AFTER transpiling typescript?
there's no TypeScript transpilation happening, as it is deferred to ESBuild.
And if you're doing it before the transpiling because if you were to do it after you would not know where the JSX was, then you could mark the function in some way (Maybe with a comment?) in order to still find it at the end
I'm not sure I understood the suggestion.
I'm not sure I understood the suggestion
Don't worry, if the transformation must happen at the TypeScript level, the suggestion doesn't apply anyway
Isn't it possible to change
export var A = _$$component(_REGISTRY, "A", function A() {
// ...
}, {
location: "..."
});
Into
import { createComponent } from "solid-js";
const RANDOM_NAME = _$$component(_REGISTRY, "A", function A() {
// ...
}, {
location: "..."
});
// Wrapper
export function A(x) {
return createComponent(RANDOM_NAME, x);
}
// Now this is allowed
export namespace A {
export const value = 56;
}
No, that would introduce some new layer of issues. I'm sorry, this might be a no-fix as TS is to be blamed here for this inconsistency. I could recommend you dropping the namespace usage (since it's not even recommended anymore by majority) but that's just one workaround.
TypeScript is not to blame this time in my opinion, because functions have always behaved differently from lambdas, It is the plugin's responsability to ensure that if I write a function then a function will come out instead of a lambda expression.
I think you shouldn't give priority to this issue, but it's something that has to be done eventually
I'm sorry but something about the current transform is never going to be touched, we haven't even solved the SSR problem with the current transform, we'll be digging a whole new level of complexity if we do this "component in a component" kind of thing (which btw, also ruins the dev experience at some point).