Borislav Hadzhiev
Fri Mar 04 2022·3 min read
Photo by Jonas Thijs
To import all exports from a file in TypeScript:
A
.B
as
import * as myNamespace from './another-file'
.myNamespace.myFunction()
in file B
.Here is an example of exporting multiple values from a file called
another-file.ts
.
// 👇️ All named exports export function getEmployee() { return { id: 1, salary: 100 }; } export type Employee = { id: number; salary: number; }; export interface Person { name: string; } export function getPerson() { return { name: 'James' }; }
Here is how we would import all of the exports into a file called index.ts
.
import * as company from './another-file'; const emp: company.Employee = company.getEmployee(); console.log(emp); // 👉️ {id: 1, salary: 100} const person: company.Person = company.getPerson(); console.log(person); // 👉️ {name: 'James'}
This pattern is called namespace imports and is used when importing a large number of things.
another-file
module if you have to. The example above assumes that another-file.ts
and index.ts
are located in the same directory.For example, if another-file.ts
was located one directory up, you'd have to
import as import * as company from '../another-file'
.
TypeScript uses the concept of modules, in the same way that JavaScript does.
The example above uses named exports.
You could have also used named imports in index.ts
and explicitly stated the
names of the imports.
// 👇️ named imports import { getEmployee, Employee, Person, getPerson } from './another-file'; const emp: Employee = getEmployee(); console.log(emp); // 👉️ {id: 1, salary: 100} const person: Person = getPerson(); console.log(person); // 👉️ {name: 'James'}
The code snipped above achieves the same goal as importing all exports from the
file via import * as company from './another-file'
.
This approach is more widely used as it is more concise and direct.
The module you are importing from might also contain a default export.
If the module you are importing from has a default export, you would import it
by removing the curly braces around its name or accessing it on the namespace as
myNamespace.default
.
// 👇️ default export export default function sum(a: number, b: number) { return a + b; }
And here is how you would import and use the default export.
import * as company from './another-file'; console.log(company.default(15, 15)); // 👉️ 30
Notice that the default export is a function named sum
, but we access it as
.default
with namespace imports.
A more intuitive approach is to import the things you need directly.
// 👇️ All named exports export function getEmployee() { return { id: 1, salary: 100 }; } export type Employee = { id: number; salary: number; }; export interface Person { name: string; } export function getPerson() { return { name: 'James' }; } // 👇️ default export export default function sum(a: number, b: number) { return a + b;
And here is how you would import the members you need.
import sum, { getEmployee, Employee, Person, getPerson } from './another-file'; const emp: Employee = getEmployee(); console.log(emp); // 👉️ {id: 1, salary: 100} const person: Person = getPerson(); console.log(person); // 👉️ {name: 'James'} console.log(sum(15, 15)); // 👉️ 30
In my experience, most real world codebases exclusively use named exports and imports, because they make it easier to leverage your IDE for autocompletion and auto-imports.
You also don't have to think about which members are exported with a default or named export.