Proper explanation for NodeJS/Typescript Export / Import?
Asked Answered
P

1

42

I am seeking information on how exports and imports work in NodeJS using TypeScript.

My setup is:

  • NodeJS
  • Everything in Typescript
  • TSLint
  • Typings

I am messing about with exports/imports instead of doing some proper coding, it's driving me nuts, and cannot find any proper explanation of how it works.

Import

What do the following mean?

var module = require ("module");

import module = require("module");

import module from "module";

import {something} from "module";

import * as module from "module";

Export

What do the following mean?

export = something;

export default something;

export interface|class something;

Questions

  • How do properly export/import a class without initiating it
  • How do properly export/import a class with it being initiated (construct did run)
  • How do I properly export/import a class and interface
  • How do I properly export/import class and multiple interfaces
  • When to use modules declarations, what are they good for and why is tslint throwing errors at me if I try to use them.

I cannot seem to find proper way of doing exports vs. imports so my IDE is not covered in red and throwing hundreds of errors at me.

General Questions

  • Is there even a way to not get errors using Nodejs/TypeScript/tslint?
  • TSLint is screaming at me for almost anything I type... it is extremely frustrating since there is no explanation to most of the errors. Is it even worth using it?

List of questions goes on and on, but I'm sure once some of the above is answered, I can pick up on the rest.

Plus answered 17/2, 2016 at 11:41 Comment(3)
Yep, dividing your TypeScript code into multiple files for separation concerns is currently on par with blashphemy. You either need to reference source files for correct ordering when using internal namespaces (!), or you need to constrain your compiled code to a module loading system (!!) syntax, so that your compiled code can run (!!!). I'm hoping this will resolve in the very near future, because at the moment TypeScript is far from being a decent choice for "application-grade Javascript development" (without a lengthy and painful project configuration, that is).Rosinweed
@JohnWhite having modules is a good thing hence their introduction to Javascript (ES6/2015). Multiple named exports can be regrouped in a single TS file. The use of namespaces in Typescript should be avoided as much as possibleIndices
@BrunoGrieder Indeed they are, but not when you are (should be) able to seamlessly compile a project into an executable resource (which is Javascript in this case). But that's just my opinion.Rosinweed
I
19

Agreed, import/export syntax is confusing for at least two reasons:

  • the commonjs syntax: var module = require ("module"); works but that is commonjs -> no typings
  • it changed: the syntax import x = require('y') is now deprecated in TS

TL;DR;: Use the 'es6 style' syntax introduced in TS 1.5

The 'best' resource on import/export in TS I know is this

Overall I recommend reading this excellent handbook which will provide answers to most of your questions

To import

From a default export

Something was exported as a default (single) export ie export default Something in ts/es6

Use

import Something from "module"

You can actually import a default export with a different name. import SomethingElse from 'module' will also work

From named exports

Something was exported as a named export in "module" using export {Something} or export class|interface Something{} in ts/es6

You want to import only that, use

import {Something} from "module"    

You want to import everything that is exported from "module" under the namespace mod

import * as mod from "module

Then use const c:mod.Something = whatever

To export

See imports above

The form export = something is deprecated in favor of the new ES6 style syntax. It is mostly found in definition files to express the fact that a js library exports a single function/object e.g. module.exports=something.

What you should try using

Use ES6 style syntax and avoid default exports: they have the advantage that they can be imported using a different name but

  • a default import cannot be re-exported, which may be problematic if you are writing a library
  • they will confuse a lot of IDEs (not to mention yourself) when refactoring
  • a named export can actually be locally renamed when imported i.e. import {Something as SomethingElse} from "module"

Concretely, export whatever needs to be exported and import it specifically

In api.ts

export interface MyInterface {
}

export class MyClass {
}

In main.ts

 import {MyInterface, MyClass} from './api'

Linting

There are a lot of good IDEs out there that provide excellent linting: VSCode, Atom Typescript and Webstorm to name a popular few, the first two being free and the third one even manages the imports for you.

Indices answered 17/2, 2016 at 12:1 Comment(2)
Would just like to add that import foo from require('foo') is an important pattern as well as some modules haven't been updated for es6. That CommonJS fallback will help. :)Ameeameer
I've found that github.com/Microsoft/TypeScript/issues/2242#issue-60179656 is a very useful summary of things as well. I also agree with avoiding export default for now. It can increase complexity in a lot of subtle ways and just isn't worth the convenience it provides.Welborn

© 2022 - 2024 — McMap. All rights reserved.