Álvaro
Álvaro

Reputation: 2588

React TypeScript - Exporting more than one component

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']
},

Upvotes: 5

Views: 1454

Answers (3)

Someone Special
Someone Special

Reputation: 13588

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';

Upvotes: 1

Álvaro
Álvaro

Reputation: 2588

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'

Upvotes: 3

Subrato Pattanaik
Subrato Pattanaik

Reputation: 6049

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.

Upvotes: 0

Related Questions