6

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.

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

9 Comments

TYVM for your answer. Could you please do me a favor and explain how "unintentional overlaying of two namespaces" shall be possible? Please be aware that I ALWAYS define the namespace in question in one single file and I ALWAYS export this namespace (like in the example above) and the namespace is never declared global.
Well, you say that you always do it exactly once... until one day you make a mistake. Or some other library you use could potentially use it. It's easy to screw up and have unexpected behavior or two merged namespaces that weren't intended to be.
If I use export namespace XYZ { ...something... } in one file and I use export namespace XYZ { ...something else.... } in another file than I have two completely different namespaces which just happens to have the same exported name and will never be merged with each other. Am I wrong?
"Namespace is considered outdated" — who says that? The TypeScript docs say nothing about that.
@Natasha I'm in the same boat - I understand the downsides of using namespace for code, but it's very useful to group types together (as your example clearly stated). Arguments against it are usually "because it's outdated", but I haven't found an objective argument against it. It's been over a year and I'm curious to hear if you continued or stopped using namespaces for types, and why?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.