My journey began with a guide on incorporating React and Webpack with TypeScript, which can be found here: https://www.typescriptlang.org/docs/handbook/react-&-webpack.html. Unfortunately, this guide did not address the issue of missing @types for the specific React component I wanted to utilize. Therefore, my initial task was to include these @types.
An interesting aspect came into play with the scoped module @foo/bar; it divided its subcomponents into individual modules like @foo/bar/X, @foo/bar/Y, and @foo/bar/Z, rendering @foo/bar itself non-functional. This unique characteristic complicated the resolution process when integrating this module into TypeScript.
I stumbled upon a helpful blog post detailing how to import plain JavaScript into TypeScript, but it fell short in some areas. Particularly, the method suggested adding "index.d.ts" to a src/@typings directory had a couple of drawbacks:
- It only worked for running the TypeScript compiler (tsc) locally, satisfying tsc's compilation requirements but failing webpack's module resolution.
- The approach did not offer insights into handling scoped modules with distinct folder naming conventions under @types.
Regardless of the technique employed, one crucial element was ensuring the presence of an import statement in my TypeScript file:
import X from '@foo/bar/X';
ReactDOM.render(
<X/>,
document.getElementById("example")
);
At some point, declaring the following in a ".d.ts" declarations file such as index.d.ts became imperative:
declare module '@foo/bar';
declare module '@foo/bar/X';
Despite these efforts, executing 'webpack' continued to produce an error stating "Module not found: Error: Can't resolve '@foo/bar/X'."
To gain more clarity, I opted to run the TypeScript compiler (tsc) with the --traceresolution flag to track the potential locations where tsc would attempt to locate the module.
tsc --traceresolution
This analysis revealed an unexpected search location under node_modules/@types, leading me to discover that tsc and by extension webpack adhered to comparable rules. Notably, tsc looked for index.d.ts file under node_modules/@types/foo__bar
, highlighting the necessity for utilizing a single folder named foo__bar
with DOUBLE UNDERSCORE for scope packages.
Armed with this knowledge, I created @types/foo__bar, mimicking the structure of the original @foo/bar module while cleaning unnecessary elements. Yet, challenges persisted as webpack still reported "
Module not found: Can't resolve '@foo/bar'
."
Further investigation utilizing 'webpack --verbose' shed light on webpack's interest in node_modules/@foo/bar/index.js—an empty enclosing module for submodules like @foo/bar/X. Addressing this discrepancy by adding an empty index.js to node_modules/@foo/bar resolved the issue, allowing my simple example, with component X, to render successfully in the browser upon loading the HTML page.