What is the purpose of exporting both a class and a namespace under the same name?

While exploring some code, I came across a situation where a class and a namespace with identical names were exported from a module. It seems like the person who wrote this code knew what they were doing, but it raised some questions for me. Could you shed light on the purpose of this practice? And is this a commonly used pattern in TypeScript?

Here's an example of what I saw in the TypeScript module:

export class MyClass {
    constructor(arg: MyClass.SubClass) {

    }
} 

export namespace MyClass {

    export interface SubClass {
        property: number
    }
}

Answer №1

Consider a scenario where having a structured approach is necessary. For instance, imagine you have your own library or app structured like this.

- src
  - views
    ListView.ts
    PinnedListView.ts
- test
  App.ts

Here is an example of how your files might look before and after implementing the structure.

Before

// ListView.ts

class ListView<A extends Adapter> {
  protected adapter?: A;
  ...
  setAdapter(adapter: A) {
    ...
  }
}

export abstract class Adapter {
  abstract id(pos: number): number;
}

export default ListView;
// PinnedListView.ts

import ListView, {Adapter} from "./ListView";

class PinnedListView<A extends PinnedListViewAdapter> extends ListView<A> {
  ...
}

export abstract class PinnedListViewAdapter extends Adapter {
  abstract shouldPin(pos: number): boolean;
}

export default PinnedListView;
// App.ts

// let's say you use path alias
import PinnedListView, {PinnedListViewAdapter} from "views/PinnedListView";

class MyAdapter extends PinnedListViewAdapter {
  // your implementation
}

const pinnedListView = new PinnedListView();
const myAdapter = new MyAdapter();
pinnedListView.setAdapter(myAdapter);

After

// ListView.ts

class ListView<A extends ListView.Adapter> {
  protected adapter?: A;
  ...
  setAdapter(adapter: A) {
    ...
  }
}

namespace ListView {
  export abstract class Adapter {
    abstract id(pos: number): number;
  }
}

export default ListView;
// PinnedListView.ts

import ListView from "./ListView";

class PinnedListView<A extends PinnedListView.Adapter> extends ListView<A> {
  ...
}

namespace PinnedListView {
  export abstract class Adapter extends ListView.Adapter {
    abstract shouldPin(pos: number): boolean;
  }
}

export default PinnedListView;
// App.ts

// let's say you use path alias
import PinnedListView from "views/PinnedListView";

class MyAdapter extends PinnedListView.Adapter {
  // your implementation
}

const pinnedListView = new PinnedListView();
const myAdapter = new MyAdapter();
pinnedListView.setAdapter(myAdapter);

Visualize a situation where there are multiple classes that need to be named Adapter, regardless of their function. This structured approach helps in keeping

  • your app organized by avoiding naming conflicts and having to prefix consuming class names before Adapter
  • readers understand clearly the purpose of each Adapter class without confusion

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Vue component prop values are not properly recognized by Typescript

Below is a Vue component I have created for a generic sidebar that can be used multiple times with different data: <template> <div> <h5>{{ title }}</h5> <div v-for="prop of data" :key="prop.id"> ...

React application facing a problem with bracket notation in Typescript

After creating a form state to store and update input changes, I encountered an issue: const [form, setForm] = useState({ user: '', email: '', password: '', }); I then wrote a function to handle form changes: const handle ...

The JSX component cannot use 'Router' as a valid element

Error Message The error message states that 'Router' cannot be used as a JSX component because its return type 'void' is not a valid JSX element. TS2786 import App from './App'; 5 | > 6 | ReactDOM.render(<Router ...

Sending data to a React component from regular HTML

I have a question about implementing a method to pass custom attributes from HTML elements as props to React components. Here's an example: function someFunction(props) { return <h1>props.something</h1> } HTML: <div id="someEl ...

Error encountered in React component: TypeScript TS2339 states that the property 'xyz' is not found on type 'IntrinsicAttributes...'

I am attempting to develop a straightforward React component that can accept any properties. The syntax below using any is causing issues (unexpected token just before <): export class ValidatedInput extends React.Component<any, any> {...} The p ...

Alert the parent angular component of any changes in the object

I am working with a large object in my component, where the properties of the object are connected to various components and inputs within the template: constructor() { this.data = { identifier: null, isRequired: true, title: ' ...

utilize makeStyles to modify button text color

Initially, my button was styled like this: style={{ background: '#6c74cc', borderRadius: 3, border: 0, color: 'white', height: 48, padding: '0 30px', }}> It worke ...

Combining Two Dropdown Selections to Create a Unique Name using Angular

I am facing a challenge with 2 dropdown values and input fields, where I want to combine the selected values from the dropdowns into the input field. Below is the HTML code snippet: <div class="form-group"> <label>{{l("RoomType")}}</labe ...

Strategies for iterating over an array in React with TypeScript

I'm currently working on looping through an array to display its values. Here's the code I have: ineligiblePointsTableRows() { return this.state[PointsTableType.INELIGIBLE].contracts.map(contract => { return { applied: (&l ...

Adjust the component suppliers based on the @input

If I were to implement a material datepicker with a selection strategy, I would refer to this example There are instances where the selection strategy should not be used. The challenge lies in setting the selection strategy conditionally when it is insta ...

How can I handle the different data type returned by ReactDom.render?

My main focus is on rendering Markdown. Additionally, I also need to parse HTML which is passed as a string. In this scenario, children represents the HTML passed as a string, while isParseRequired indicates if parsing is needed. import cx from 'clas ...

Receiving an error in Typescript when passing an object dynamically to a React component

Encountering a typescript error while attempting to pass dynamic values to a React component: Error message: Property 'title' does not exist on type 'string'.ts(2339) import { useTranslation } from "react-i18next"; import ...

Next.js TypeScript project encountered an issue: "An error occured: 'TypeError: Cannot read property 'toLowerCase' of undefined'"

I am currently developing a Next.js TypeScript project and am facing a perplexing runtime error. The error message reads: TypeError: Cannot read property 'toLowerCase' of undefined This error is triggered in my code when I try to invoke the toLo ...

Exploring how NestJS can serialize bigint parameters within DTOs

I have data transfer objects (DTOs) with parameters that are of type bigint. However, when I receive these DTOs, the parameters always have a type of string. Here is an example: @Get("") async foo(@Query() query: Foo) { console.log(typeof Foo ...

Vue: rendering props cannot be utilized with TSX

After switching my setup from JSX in a Vue component to TS with vue-class-component, I found that only the code snippet below works for me (as shown in the example on repo): import Vue from 'vue' import { Component } from 'vue-property-dec ...

The seamless pairing of Cucumber and Playwright: Cucumber's inability to retain cookies results in a login attempt with every scenario

I am currently facing an issue with integrating cucumber and playwright into my framework. When attempting to execute various features or multiple scenarios within one feature, I encounter a problem where if one scenario logs into a site, the other scenari ...

What issue are we encountering with those `if` statements?

I am facing an issue with my Angular component code. Here is the code snippet: i=18; onScrollDown(evt:any) { setTimeout(()=>{ console.log(this.i) this.api.getApi().subscribe(({tool,beuty}) => { if (evt.index == ...

Attempting to eliminate any dates that have already occurred

I am faced with an array containing various dates in string format such as "2016-08-12". My goal is to eliminate any dates that have already passed by comparing them to today's date. I am using TypeScript for this task. Here is a snippet of my datoAr ...

Disabling the scrollbar within angular elements

Trying to remove the two scrollbars from this code, but so far unsuccessful. Attempted using overflow:hidden without success filet.component.html <mat-drawer-container class="example-container" autosize> <button type="button&qu ...

How can I exclude the 'node_modules' directory but still include specific subfiles in the tsconfig file for TypeScript?

My tsconfig file is structured as follows: { "compileOnSave": false, "compilerOptions": { "module": "es2015", "target": "es2015", "sourceMap": true, "jsx": "react", "allowSyntheticDefaultImports": true, "noImplicitAny": false, ...