-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to import
JSX types, Error: "no interface JSX.IntrinsicElements exists", although it exists
#41813
Comments
If libraries could export non-global versions of JSX types, then projects could very easily have a mix of files where each file may have a different type of JSX (f.e. React in some files, Preact in others, and Solid.js in others, assuming those libs export non-global JSX types). |
namespace JSX {
export interface Element {
// ^^^^^^
foo: number
}
export interface IntrinsicElements {
// ^^^^^^
div: HTMLDivElement
}
}
const d = <div></div> |
They can. |
Ahh, thanks! I never use |
Turns out it actually does not work when This does not work: // WHILE THIS WORKED
// namespace JSX {
// export interface Element {
// foo: number
// }
// export interface IntrinsicElements {
// div: {foo: number, bar: string}
// }
// }
// THIS DOES NOT
import type {JSX} from 'solid-js'
const d = <div foo={123} bar="string"></div> // JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists. We can verify type test = JSX.IntrinsicElements // The type exists! It doesn't seem right for Note, A solution in 4.1.1 is to use |
Please note, the I also tried converting that file to a |
You wanna use the |
Thing is, I don't want any jsx pragma. I'm using But still, JSX types are in scope, and TS is not picking it up. I don't think there should be any difference between an inline declaration and an import with regards to visibility. JSX shouldn't have special treatment. |
We have an existing There is a new I think that import {JSX} from `somewhere`
// or
import type {JSX} from `somewhere` should just work. I really feel there isn't a need to make JSX a specially-treated type when it comes to making it visible in a scope. |
You can still use the pragma with |
(Also, we didn't "invent" the comment pragma syntax - we just copied it from babel) |
We should be able to
and be done. I can't think of a good reason to have this stuff coupled to specific files or coupled to React. The "runtime" in After fixing
But it would be best to simply allow |
TypeScript playground does not install dependencies for If we could instead rely on |
Besides when I realized that we have to import JSX twice in order to use it in both normal code, and with JSX expressions. This is WET instead of DRY. So in order for the following code to work, we must import JSX in the same file using both syntaxes: /* @jsxImportSource solid-js */
// ^ FIRST IMPORT
import { createState, onCleanup, Component, JSX } from "solid-js";
// ^ SECOND IMPORT
import { render } from "solid-js/web";
const App: Component = () => {
const [state, setState] = createState({ count: 0 }),
timer = setInterval(() => setState("count", (c) => c + 1), 1000);
onCleanup(() => clearInterval(timer));
// The @jsxImportSource comment is needed for this JSX expression to recognize the <div> intrinsic element.
return <div>{state.count}</div>;
};
render(() => <App />, document.getElementById("app"));
// The `import {JSX} from "solid-js"` is needed in order to use the JSX types in non-JSX expressions
interface Foo extends JSX.HTMLAttributes<HTMLDivElement> {} Try it here live in your browser, or clone the repo, and run I hope by now you may be convinced that |
import
JSX types, Error: "no interface JSX.IntrinsicElements exists", although it exists
@weswigham I updated the OP to make it clear based on the new findings regarding |
I appreciate your consideration on this issue. At this point I'm fairly used to having most of the ecosystem assume JSX === VDOM factory function because Babel/TypeScript ship with a default JSX transform. But the spec for JSX makes no mention of what the output should be only indicates the syntax. I'm happy to have any solution at all. Even it is simply from the fact that React decided one day to have a new version that doesn't rely on a pragma import. The pre 4.1.1 solutions were horrendous, so I will happily follow predefined file paths for types if it accomplishes the goal. I understand since you did not invent the syntax for jsxImportSource you can't really change its function, but importing JSX working seems like it could be reasonable. |
We do two things to find JSX types:
We have never looked for a locally scoped namespace named |
Right, Global though is basically a mess. You can't have multiple JSX providers in the same project using Global they attack each other and it is completely broken. In those scenarios it is basically a non-starter. I strongly dislike the assumption JSX has a single factory function. It is very narrow view that isn't true. From Inferno's precompiled VDOM, Solid's custom DOM transformations.. It is not a coincidence these also happen to be the most performant JSX libraries. You will see more optimizations of this nature in the future for performance reasons. Guaranteed. I would expect similar from Vue at some point and I wouldn't count React out in the future. There are plenty of things that JSX can generate and do. So So it could be beneficial to have a native TypeScript solution, but I do understand if the plan is just continue keeping this perspective and follow Babel's lead. Interestingly Babel itself does a pretty good job following the spec in terms of their syntax support, whereas TypeScript has historically tuned the implementation to match React. |
I agree. This discludes other forms of JSX that do not have factory functions (like @ryansolid's Solid.js is quite amazing), and it means they would have to define a fake type for something that doesn't actually exist.
Disregarding that, I really don't see why we can't just have If @weswigham Have you used more than one form of JSX in a single project before? It is a real big pain. I believe |
The
It really makes much sense to support
You should honestly remove the strange things. But even if you keep them, The very first thing I thought was: I'll just import It makes so much sense! |
Note, Babel's new This is unfair to the rest of the JSX ecosystem, and TypeScript is not providing a more fair and desirable playground for other JSX libraries. React incubated JSX, a language spec, not a runtime spec. |
@trusktr Can you please log a new concrete suggestion issue for supporting that? Piling on more comments to something that was filed as a bug is very confusing for us; if we want to have a real discussion on that point it's very awkward that we'd have to scroll down n comments to understand what the issue was really about. |
@RyanCavanaugh I think the OP describes the issue fairly well. I don't think a new issue would be needed. |
@weswigham @RyanCavanaugh Mind re-opening the issue? The OP describes the issue exactly, there is no need for a new one. But I can make a duplicate if you confirm that would be better. |
TypeScript Version: 4.1.2
Search Terms:
no interface JSX.IntrinsicElements exists
Code
This works:
playground
But this does not work:
playground
Expected behavior:
It should see the definition of
JSX.IntrinsicElements
which is clearly present due to theimport
statement.Actual behavior:
The JSX definition in the second example (
import
ed) appears to be invisible to TS.As you can see from both examples, only a locally-defined
JSX
works, but not one that isimport
ed.The text was updated successfully, but these errors were encountered: