Question

TypeScript export vs default export: What’s the Difference?

typescriptjavascriptecmascript-6

Question

What is the difference between export and export default in TypeScript?

In many tutorials, classes are exported, but my code does not compile unless I add the default keyword before the class export.

For example, this does not work in my project:

export class MyClass {
  collection = [1, 2, 3];
}

But this does work:

export default class MyClass {
  collection = [1, 2, 3];
}

The compiler error is:

error TS1192: Module '"src/app/MyClass"' has no default export.

Why does this happen, and how should export and export default be used correctly in TypeScript?

Short Answer

By the end of this page, you will understand the difference between named exports and default exports in TypeScript, how they affect import syntax, why the TS1192 error appears, and how to choose the right export style in real code.

Concept

TypeScript modules can export values in two common ways:

  • Named export using export
  • Default export using export default

The important difference is how the value must be imported.

Named export

When you write:

export class MyClass {
  collection = [1, 2, 3];
}

MyClass is a named export. That means other files must import it by its exact exported name using curly braces:

import { MyClass } from './MyClass';

Default export

When you write:

export default class MyClass {
  collection = [1, 2, 3];
}

The module has a default export. That means other files can import it without curly braces:

import MyClass from './MyClass';

You can even rename it during import:

import SomethingElse from './MyClass';

Why your error happens

This error:

TS1192: Module '.../MyClass' has no default export.

usually means:

  • your file exports MyClass as a named export, but
  • another file is trying to import it as a default export

For example, this causes the error:

// MyClass.ts
export class MyClass {
  collection = [1, 2, 3];
}

// Another file
import MyClass from './MyClass'; // Error: no default export

The import does not match the export type.

Why this matters

This is one of the most common module mistakes in TypeScript and JavaScript projects. If you understand export styles, you can:

  • organize code into reusable modules
  • avoid import errors
  • read tutorials more confidently
  • work with libraries that use different export styles

The issue is not that export fails to compile by itself. The issue is usually that the import statement does not match the export statement.

Mental Model

Think of a module like a box of tools.

  • A named export is like putting labels on specific tools inside the box: hammer, wrench, screwdriver.
  • A default export is like saying: "If you take just one main thing from this box, take this one."

Named export

You must ask for the exact labeled tool:

import { MyClass } from './MyClass';

Default export

You are taking the module's main item, so no label lookup is needed:

import MyClass from './MyClass';

If you ask for the default item when the box only contains labeled tools, TypeScript complains. That is what your error means.

Take Quiz

Syntax and Examples

Core syntax

Named export

// MyClass.ts
export class MyClass {
  collection = [1, 2, 3];
}

Import it like this:

import { MyClass } from './MyClass';

const item = new MyClass();
console.log(item.collection);

Default export

// MyClass.ts
export default class MyClass {
  collection = [1, 2, 3];
}

Import it like this:

import MyClass from './MyClass';

const item = new MyClass();
console.log(item.collection);

Exporting multiple values

Named exports are often used when a file exports more than one thing:

export class MyClass {
  collection = [1, 2, 3];
}

export function sum(values: number[]) {
  return values.reduce((a, b) => a + b, 0);
}

Import them like this:

import { MyClass, sum } from './MyClass';

Combining named and default exports

A module can have one default export and also named exports:

export default class MyClass {
  collection = [1, 2, 3];
}

export const version = '1.0';

Import them like this:

import MyClass, { version } from './MyClass';

Beginner-friendly rule

  • If you exported with export, import with {}
  • If you exported with export default, import without {}

Step by Step Execution

Consider this example:

// MyClass.ts
export class MyClass {
  collection = [1, 2, 3];
}

// app.ts
import { MyClass } from './MyClass';

const obj = new MyClass();
console.log(obj.collection);

What happens step by step

1. MyClass.ts defines a class

export class MyClass {

This creates a class named MyClass.

2. export makes it available to other files

Because it uses export, this class becomes a named export of the module.

3. app.ts imports the named export

import { MyClass } from './MyClass';

The curly braces tell TypeScript: "Find the export named MyClass in that file."

4. A new object is created

const obj = new MyClass();

This calls the class constructor and creates an instance.

5. The property is printed

console.log(obj.collection);

Output:

[1, 2, 3]

Now the broken version

// MyClass.ts
export class MyClass {
  collection = [1, 2, 3];
}

// app.ts
import MyClass from './MyClass';

Why it fails

  • MyClass.ts exports a named export
  • app.ts tries to import a default export
  • There is no default export in the file
  • TypeScript raises TS1192

Fixed version 1: keep named export

import { MyClass } from './MyClass';

Fixed version 2: switch to default export

// MyClass.ts
export default class MyClass {
  collection = [1, 2, 3];
}

// app.ts
import MyClass from './MyClass';

Real World Use Cases

1. Exporting utility functions

Named exports are common in utility files:

export function formatDate(date: Date) {
  return date.toISOString();
}

export function parseDate(value: string) {
  return new Date(value);
}

This makes it easy to import only what you need:

import { formatDate } from './dateUtils';

2. Exporting one main component or class

Default exports are often used when a file has one primary thing:

export default class UserService {
  getAllUsers() {
    return ['Ava', 'Noah'];
  }
}

Imported like this:

import UserService from './UserService';

3. React components

Many React codebases use default exports for components, though named exports are also common:

export default function Button() {
  return 'Click';
}

4. Configuration files

A configuration module often exports one main object:

const config = {
  apiUrl: 'https://api.example.com',
  timeout: 5000,
};

export default config;

5. Shared constants and helpers

Named exports are useful when a file contains several related values:

export const MAX_RETRIES = 3;
export const TIMEOUT_MS = 5000;
export function isRetryable(code: number) {
  return code >= 500;
}
Take Quiz

Real Codebase Usage

In real projects, the choice between named and default exports is usually based on consistency and team preference.

Common named export patterns

Utility modules

export function isEmail(value: string) {
  return value.includes('@');
}

export function isPasswordStrong(value: string) {
  return value.length >= 8;
}

Validation helpers

export function validateUserName(name: string) {
  if (!name.trim()) {
    throw new Error('Name is required');
  }
}

Re-exporting from index files

export { MyClass } from './MyClass';
export { UserService } from './UserService';

This is common in shared libraries.

Common default export patterns

One main class per file

export default class ApiClient {
  get(url: string) {
    return `GET ${url}`;
  }
}

Main configuration object

const settings = {
  env: 'development',
};

export default settings;

Team conventions

Many teams prefer named exports because:

  • imports are explicit
  • renaming accidentally is harder
  • auto-import tools often work more predictably
  • refactoring is easier in large codebases

Some teams prefer default exports when:

  • each file has one obvious main value
  • the import syntax should be shorter

Practical rule in codebases

Use one style consistently. Most confusion comes not from either syntax itself, but from mixing them carelessly.

Common Mistakes

1. Importing a named export as if it were default

Broken code:

// MyClass.ts
export class MyClass {}

// app.ts
import MyClass from './MyClass';

Why it fails:

  • MyClass is a named export
  • the import expects a default export

Fix:

import { MyClass } from './MyClass';

2. Importing a default export with curly braces

Broken code:

// MyClass.ts
export default class MyClass {}

// app.ts
import { MyClass } from './MyClass';

Fix:

import MyClass from './MyClass';

3. Forgetting that named imports must match the exported name

Broken code:

// MyClass.ts
export class MyClass {}

// app.ts
import { SomethingElse } from './MyClass';

Fix:

import { MyClass } from './MyClass';

Or rename it explicitly:

import { MyClass as SomethingElse } from './MyClass';

4. Assuming tutorials always use the same module settings

Some tutorials may use different TypeScript or bundler settings. That can affect import behavior, especially when working with CommonJS or interop options.

If a tutorial seems inconsistent, check:

  • the export syntax in the source file
  • the import syntax in the consuming file
  • tsconfig.json settings

5. Mixing styles without a reason

This is valid:

export default class MyClass {}
export const version = '1.0';

But overusing mixed exports can confuse beginners. Start simple and stay consistent.

6. Thinking export is invalid because of the compiler error

The problem is usually not the export statement itself. The problem is the matching import statement elsewhere in the code.

Comparisons

Featureexportexport default
Export typeNamed exportDefault export
Import syntaximport { MyClass } from './MyClass'import MyClass from './MyClass'
Uses curly bracesYesNo
Must match exported nameYesNo
Can a file have many of these?YesOnly one default export
Common useUtilities, helpers, multiple exportsOne main class, component, or config

Named export vs default export example

// named
export class MyClass {}
import { MyClass } from './MyClass';
// default
export default class MyClass {}
import MyClass from './MyClass';

Which should you choose?

SituationBetter choice
File exports several helpersNamed exports
File has one obvious main thingDefault export or named export, depending on team style
Large codebase with strong consistency needsOften named exports
Shorter import syntax is preferredDefault export
Take Quiz

Cheat Sheet

Quick rules

  • export = named export
  • export default = default export
  • Named exports are imported with {}
  • Default exports are imported without {}
  • A file can have many named exports
  • A file can have only one default export

Syntax

Named export

export class MyClass {}
import { MyClass } from './MyClass';

Default export

export default class MyClass {}
import MyClass from './MyClass';

Multiple named exports

export const a = 1;
export const b = 2;
import { a, b } from './file';

Default + named together

export default class MyClass {}
export const version = '1.0';

import MyClass, { version } from './MyClass';

Error to remember

TS1192: Module has no default export

Usually means:

// Exported as named
export class MyClass {}

// Imported as default by mistake
import MyClass from './MyClass';

Fix checklist

  • If the file uses export, import with curly braces
  • If the file uses export default, import without curly braces
  • Check the exact exported name for named imports
  • Keep your project style consistent

FAQ

Why do I get "Module has no default export" in TypeScript?

Because you are importing a module as if it had a default export, but the file only exports named values.

Is export default required for classes in TypeScript?

No. Classes can be exported either as named exports or as a default export. The import syntax must match.

Why do some tutorials use export default and others use export?

Because both are valid. Different projects and teachers prefer different module styles.

Can I have both export default and named exports in the same file?

Yes. A file can have one default export and any number of named exports.

Which is better: named exports or default exports?

Neither is always better. Named exports are often preferred in larger codebases for clarity. Default exports are convenient when a file has one main value.

Can I rename imports?

Yes.

For named exports:

import { MyClass as CustomName } from './MyClass';

For default exports:

import CustomName from './MyClass';

Does TypeScript documentation support export default?

Yes. It is part of the module system TypeScript supports. If you do not see it in one specific page, that does not mean it is unsupported.

Is this a TypeScript problem or a JavaScript module problem?

Mostly a module syntax problem. TypeScript follows JavaScript module rules and adds type checking on top.

Take Quiz

Mini Project

Description

Build a small TypeScript module setup with one file exporting a class and helper function, then import them correctly in another file. This project demonstrates the difference between named exports and default exports in a realistic but simple way.

Goal

Create two modules and import their exports correctly without triggering TS1192.

Requirements

  1. Create one file that uses a named export for a class.
  2. Create one file that uses a default export for a configuration object.
  3. Import both correctly in a main file.
  4. Instantiate the class and print one property.
  5. Read and print a value from the default-exported configuration.
Take Quiz

Keep learning

Related questions

View more