Skip to content
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 #47072

Closed
trusktr opened this issue Dec 8, 2021 · 7 comments
Assignees
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@trusktr
Copy link
Contributor

trusktr commented Dec 8, 2021

TypeScript Version: 4.5.2

Search Terms:

no interface JSX.IntrinsicElements exists

Code

import type {JSX} from 'solid-js'

type test = JSX.IntrinsicElements // <-- no error, the type exists.

const d = <div /> // Error: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.

playground

Expected behavior:

It should see the definition of JSX.IntrinsicElements which is present due to the import statement.

Actual behavior:

"no interface JSX.IntrinsicElements exists"

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Dec 9, 2021
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 4.6.0 milestone Dec 9, 2021
@weswigham weswigham added Working as Intended The behavior described is the intended behavior; this is not a bug and removed Needs Investigation This issue needs a team member to investigate its status. labels Dec 9, 2021
@weswigham
Copy link
Member

I explained this to you in the other issue with mostly the same premise you commented in; we don't look for a local name JSX, only a global one, nor do we document doing so anywhere, nor do we want to add a 3rd way to find JSX definitions, beyond the global method (which is around for legacy reasons), and the factory-local method (which works for any library which defines a JSX namespace under their factory function).

@weswigham
Copy link
Member

Yeah, this is a dupe of #41813.

@trusktr
Copy link
Contributor Author

trusktr commented Dec 10, 2021

@weswigham I also previously explained all the issues, summarized here:

This goes against developer intuition: devs expect that importing something makes it visible.

Tools relying on static analysis of import statements are built around import syntax, not around non-standard @jsxImportSource syntax.

VS Code's Go To Definition has no idea what to do with @jsxImportSource syntax, despite being powered by TypeScript.

Screenshot 2021-12-09 163646

Screenshot 2021-12-09 163716

Using the @jsxImportSource syntax to import JSX.... doesn't work:

Screenshot 2021-12-09 164414

TS playground even gets bugged out:

Screenshot 2021-12-09 170305

What's worse is, if a global type package like @types/react is in place, the wrong JSX type will be used on accident. Even if @jsxImportSource solid-js is used at the top of a file. Running Go To Definition on JSX in that previous example,

Screenshot 2021-12-09 164856

will take you to this,

Screenshot 2021-12-09 165050

which is confusing.

To get around this issue, we have to import JSX twice:

/* @jsxImportSource solid-js */
import {JSX} from 'solid-js'

type test = JSX.IntrinsicElements

function Foo() {
    return <div />
}

(playground)

Is this really "working as intended"? I'd place bets that supporting import syntax would solve these issues cleanly.

@weswigham
Copy link
Member

The JSX namespace of a package should never be the place you go to to find types for it - they're an ugly implementation detail to tell the compiler how JSX works for them - there's a reason all the entries in the react JSX namespace that can be are pointers to other types outside the JSX namespace.

Hell, part of the reason we don't let a local JSX name interfere with jsx resolution is so those ugly implemention details don't interfere with working with normal stuff, so you can still use the name "JSX" in code and not have it break your JSX!

@trusktr
Copy link
Contributor Author

trusktr commented Dec 10, 2021

I can't make much sense of that reasoning. If someone writes import JSX from 'wherever', then obviously they can't make an additional identifier of the same name within scope (apart from performing type augmentation). This is fully expected from ES Modules; no one is going to have an issue with that.

Plus, the fact that JSX expressions are type checked, doesn't seem like an implementation detail. It seems people heavily rely on a JSX type. Sure, change the JSX expression type checking semantics if you want to (f.e. the other topic about JSX factory return types), but it really doesn't have to do with the how types are imported. JSX is not a hidden type, and if JSX expresion type semantics change, any types used for type checking (if no longer JSX) will still not be hidden, and should be imported. It's simply intuitive.

The way it currently works is more confusing that it could be (now, I don't know who specifically wrote it, and it shouldn't be taken in any offense, I'm just describing as an end user what I think would be intuitive).

@ryansolid
Copy link

I find it amusing this got closed as a duplicate when @trusktr was specifically instructed in the other issue to make this as a new issue. It's clear there is no interest by maintainers to address this, which your prerogative but it does seem like there are gaps in the current implementation with no solution in sight. I'm sure there are good reasons not to address this. Might be good to at least talk to that.

@weswigham
Copy link
Member

He was asked for a concrete proposal - repeating the same bug report as the other OP makes it a pretty clear duplicate, since this is a "bug" report that is, in fact, "working as intended" as written. Unless you wanna propose a new behavior (which I've already said (in both issues) why I don't support the new behavior he'd probably want to propose) with the "feature request" template and actually write out why someone would want JSX to work in this new way (in detail), what advantages it offers and disadvantages vs current mechanisms for the same, and the details of how it should actually work alongside existing behavior without breaking code in the wild, because what's being alluded to is definitely a new feature. One I obviously don't support, as my comments should make clear, so I won't make such a proposal myself, but hey, if you make a compelling proposal and change other team members hearts and minds (or mine) I can't stop you~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants