Question

Typescript error TS2307: Cannot find module 'react' when trying to import without using node.js?

I am new to React and TypeScript and am trying to build the most minimal example app that can be compiled and hosted on a bare IIS development web server. I'm running into this error when compiling with the tsc command:

PS C:\inetpub\wwwroot\TypeScriptReactTest> tsc

test.ts:1:24 - error TS2307: Cannot find module 'react' or its corresponding type declarations.

1 import * as React from 'react';

I am using TypeScript 5.5.2 and React+ReactDOM 18.2. The react scripts are loaded in my HTML via a CDN, not referenced locally. (I need the CDN approach to work as we are evaluating switching new development to React, so performance is a concern and all common libraries need to be loaded via CDN if possible.)

My app has only these 3 files:

test.ts:

import * as React from 'react';
import * as ReactDOM from 'react-dom';

const sHelloPrefix: string = "Hello,";

class HelloComponent extends React.Component {
    render() {
        return React.createElement("div", null, `${sHelloPrefix} ${this.props.toWhat}`);
    }
}

document.addEventListener("DOMContentLoaded", () => {
    const oReactRoot = ReactDOM.createRoot(document.getElementById("app"));
    oReactRoot.render(React.createElement(HelloComponent, {toWhat: "World! (from TS)"}));
});

test.html:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TypeScript/React test</title>
    </head>
    <body>
      <div id="app"></div>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js" integrity="sha512-m7nhpWHotpucPI37I4lPovL28Bm2BhAMV8poF3F8Z9oOEZ3jlxGzkgvG0EMt1mVL1xydr1erlBbmN90js/ssUw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js" integrity="sha512-I5GJQRKGdj2miDs8ComgARfiAQiZJo/43YasH22qtweoG+YRXLTDYegxC/vPgw/ERxRzww/F4l4+8UiMmI20sw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        <script src="test.js"></script>
    </body>
</html>

tsconfig.json:

{
    "compilerOptions": {
        "target": "es2020",
        "module": "NodeNext",
        "moduleResolution": "NodeNext",
        "strict": true,
        "noEmitOnError": true
    },
    "include": [
        "**/*.ts"
    ],
    "exclude": [
        "**/*.js"
    ]
}

Things I have tried:

  • npm install -g -D typescript@5.5.2
  • npm install -g -D react@18.2
  • npm install -g -D react-dom@18.2
  • npm install -g -D @types/react-dom@18.2
  • npm install -g -D @types/react@18.2

I have set up similar app at https://jsfiddle.net/noj206zp/2/ which works, but I don't understand why. It's not importing React anywhere in the .ts file, so I think JSFiddle is doing some magic in the background that I am not doing in my local IIS app.

 3  90  3
1 Jan 1970

Solution

 1

for your tsconfig file, try below one-

{
    "compilerOptions": {
        "target": "es2020",
        "module": "esnext",
        "moduleResolution": "node",
        "strict": true,
        "jsx": "react",
        "noEmitOnError": true,
        "esModuleInterop": true,
        "skipLibCheck": true
    },
    "include": [
        "**/*.ts",
        "**/*.tsx"
    ],
    "exclude": [
        "node_modules",
        "**/*.js"
    ]
}

if the above doesn't work add - globals.d.ts in your root dir (this declares React and ReactDOM as global variables )

declare var React: typeof import('react');
declare var ReactDOM: typeof import('react-dom');

then run tsc to compile the file, also ensure your test.html includes the compiled JavaScript file properly. this should work i guess, let me know!

2024-06-30
ishaan

Solution

 0

I resolved the issue by installing react, react-dom, and their corresponding @types packages for each in the project root using npm. I then stripped down the tsconfig.json file to the bare minimum needed to compile successfully. For some reason, I also had to remove the { props.toWhat } thing, but I think that's unrelated:

npm install react@18.2
npm install react-dom@18.2
npm install @types/react@18.2
npm install @types/react-dom@18.2

test.ts

import * as React from 'react';
import * as ReactDOM from 'react-dom/client';

const sHelloPrefix: string = "Hello,";

class HelloComponent extends React.Component {
    render() {
        return React.createElement("div", null, `${sHelloPrefix} World`);
    }
}

document.addEventListener("DOMContentLoaded", () => {
    const oReactRoot = ReactDOM.createRoot(document.getElementById("app")!);
    oReactRoot.render(React.createElement(HelloComponent, null));
});

test.html:

No change, same as in question above.

tsconfig.json:

{
    "compilerOptions": {
        "target": "es2020",
        "moduleResolution": "node",
        "strict": true,
        "noEmitOnError": true
    },
    "include": [
        "**/*.ts"
    ]
}

TypeScript now compiles test.ts to test.js successfully. But now I have a different error. My browser is throwing "Uncaught SyntaxError: import declarations may only appear at top level of a module" when the page loads. I think this is because TypeScript is assuming that my app will be running in an environment that supports modules, but the browser doesn't like that. Adding type="module" to the tag resolves that error but throws a new one: Uncaught TypeError: The specifier “react” was a bare specifier, but was not remapped to anything. Relative module specifiers must start with “./”, “../” or “/”..

Since these errors are separate from my original question, I will mark this answered and consider posting a new question if I can't resolve them.

2024-07-02
Jordan Rieger