React TypeScript - Exporting more than one component

Viewed 799

Given this folder structure:

├──components/
|  └─Elements/
|    └─Button/
|    └─Input/
|    └─index.ts
|  └─Home/
|    └─home.tsx

I would like to export Button and Input so I can access them from the home component by doing:

home.tsx

import { Button, Input } from '@elements/'

I have tried this:

index.ts (in Elements folder)

export { Button } from './Button/button';
export { Input } from './Input/input';

But it does not work, I get: Cannot find module '@elements/' or its corresponding type declarations. even thou the resolve alias does work.

tsconfig.json

{
  "compilerOptions": {
    "outDir": "../public",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "baseUrl": "./",
    "rootDir": "./",
    "typeRoots": ["./node_modules/@types", "./src/@types"],
    "paths": {
      "@src/*": ["src/*"],
      "@images/*": ["src/images/*"],
      "@styles/*": ["src/styles/*"],
      "@components/*": ["src/components/*"],
      "@elements/*": ["src/components/Elements/*"],
    },
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "importsNotUsedAsValues": "preserve"
  },
  "exclude": ["node_modules", "webpack"]
}

webpack.config.babel.js

...
resolve: {
  alias: [
    '@src': join(rootDir, '/src'),
    '@images': join(rootDir, '/src/images'),
    '@assets': join(rootDir, '/src/assets'),
    '@styles': join(rootDir, '/src/styles'),
    '@components': join(rootDir, '/src/components'),
    '@elements': join(rootDir, '/src/components/Elements')
  ]
  extensions: ['.tsx', '.ts', '.js', '.jsx']
},

3 Answers

I found the solution to be removing the * from the path declaration on tsconfig.json

This

"@elements/*": ["src/components/Elements/"]

Instead of this

"@elements/*": ["src/components/Elements/*"]

And then importing it by using

import { Button, Input } from '@elements/'

or

"@elements": ["src/components/Elements"]
import { Button, Input } from '@elements'
import { Button } from './Button/button';
import { Input } from './Input/input';

should probably be

export { Button } from './Button/button';
export { Input } from './Input/input';

If they are default exports, you have to do this.

export { default as Button } from './Button/button';
export { default as Input } from './Input/input';

Module resolution in Typescript is the process that the compiler uses to figure out what an import refers to. You can read more on module resolution in the Typescript Handbook.

import { Button } from './Button/button';

This type of import is called a relative import. A relative import is one that starts with /, ./ or ../.

Any other import is considered non-relative. Some examples include:

import * as $ from "jquery";
import { Component } from "@angular/core";

There is two module resolution strategy in typescript which is node and classic. By default module resolution is set to classic.

Set the module resolution to node would solve your problem.

"moduleResoution": "node"

Note: node module resolution is the most-commonly used in the TypeScript community and is recommended for most projects. If you are having resolution problems with imports and exports in TypeScript, try setting moduleResolution: "node" to see if it fixes the issue.

Related