Natasha
Natasha

Reputation: 766

Using namespaces in TypeScript, but only for types => anti-pattern?

From time to time folks tell you that you should not use namespaces in TypeScript. For example here: https://typescript-eslint.io/rules/no-namespace/ (eslint error: "ES2015 module syntax is preferred over namespaces")

Of course I know what an ES module is and of course my TS code is essentially structured in ES modules.

Nevertheless in certain cases (UI components, complex events etc.) I use namespaces to bundle types (only types!), to make it easier to import and use those types later. See the following example (this is some kind of UI component). The important thing is that later by using import { Button } from 'xyz' you have access to the function Button itself and all the types Button.Type, Button.Variant and Button.Size which I consider extremely handy.

export { Button };

namespace Button {
  export type Type = 'button' | 'submit' | 'reset';
  export type Variant = 'default' | 'primary' | 'warning' | 'danger';
  export type Size = 'small' | 'medium' | 'large';
}

function Button(props: {
  type?: Button.Type;
  variant?: Button.Variant;
  size?: Button.Size;
  // ... and others ...
}) {
  // not important
}

[Edit: Please consider this example as a part of a widget library, not an application]

Do you consider this an anti-pattern? Please explain your answer.

Upvotes: 5

Views: 1849

Answers (1)

Jason Byrne
Jason Byrne

Reputation: 1619

As you said, Namespace is considered outdated. It's best to avoid it. Instead do something like:

button.ts

export type Type = 'button' | 'submit' | 'reset';
export type Variant = 'default' | 'primary' | 'warning' | 'danger';
export type Size = 'small' | 'medium' | 'large';

app.ts

import * as Button from './button'

function createButton(props: {
    type?: Button.Type;
    variant?: Button.Variant;
    size?: Button.Size;
  }) {
    // do something here
}

As for why it's outdated or discouraged, well, for one thing, it can cause conflicts and unintentional overlaying of two namespaces. The pattern above puts you in the driver's seat when you import it.

Upvotes: 2

Related Questions