#NodeNext targets with custom `jsxImportSource` results in generated code missing .js extension.

18 messages · Page 1 of 1 (latest)

elder matrix
#

The below is my tsconfig:

{
  "$schema": "https://json.schemastore.org/tsconfig",
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "NodeNext",
    "skipLibCheck": true,
    "moduleResolution": "NodeNext",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "react-jsx",
    "jsxImportSource": "@kitajs/html",
    "outDir": "dist",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "types": [ "node"],
    "plugins": [{ "name": "@kitajs/ts-html-plugin" }]
  },
  "include": ["src"]
}

And I simply have this code:

function Entry(props: PropsType) {
  return (
    <tr>
      <td safe>{props.entry.id}</td>
      <td safe>{props.entry.name}</td>
    </tr>
  );
}

It gives me this error:

Cannot find module '@kitajs/html/jsx-runtime' or its corresponding type declarations.ts(2307)

Which is correct because with NodeNext I need to use .js as a extension when importing files. How can I force typescript to add .js extension in automatic jsx runtime import it does???

Is this a bug in typescript?

#

The correct import should be import '@kitajs/html/jsx-runtime.js';

winter cosmos
#

this is the expected behavior

#

TS doesn't change the imports in your code

#

the imports you write in TS are the imports you get in the emitted JS

#

you can either:

  • use a bundler to ignore imports alltogether and have a single code bundle
  • add .js at the end of your import paths (yes, .js even in the TS code)
  • use a different compiler that can change the emitted paths for the imports
elder matrix
#

but that's the point

#

I do not add the jsx runtime import

#

when the jsx target is react-jsx the import is not required

#

as ts does it for us as:

import { jsx as _jsx, jsxs as_jsxs } from '<whatever is in jsxImportSource>/jsx-runtime'
winter cosmos
#

@elder matrix jsxImportSource usually refers to an entier npm package which contains the jsx-runtime
and ofc it won't work in the browser, since

  • ESM doesn't use index.js as the default file for folder imports
  • browsers require a file extension for the file imports
#

it's not possible to only use tsc and have an out-of-the box valid code

#

it's by design

#

also, jsxImportSource lets you specify the jsx-runtime for convenience, but you might still need to import other things to make the whole code work

#

just as described in the preact docs
need to import h manually in each TSX file
even tho it's not used directly

#

if you want a more advanced/custom JSX compilation, you should use an actual transpiler (babel, esbuild, parcel, etc.)

elder matrix
#

I went to see why with react itself it works but not with other JSX runtimes, turns out react has a /jsx-runtime field in their package.json exports. I just needed to also add in on my own runtime