Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Please add typescript namespaces support #8236

Closed
vegansk opened this issue Dec 25, 2019 · 4 comments
Closed

Please add typescript namespaces support #8236

vegansk opened this issue Dec 25, 2019 · 4 comments

Comments

@vegansk
Copy link

vegansk commented Dec 25, 2019

Is your proposal related to a problem?

We heavily use typescript namespaces to group algebraic data types constructors, but CRA doesn't support it because of babel's default allowNamespaces setting value. And that's why we can't use CRA.

Describe the solution you'd like

Set allowNamespaces setting to true or allow to configure it somehow.

@heyimalex
Copy link
Contributor

There are currently caveats to babel's namespace support, and we generally prefer to not enable features that may work in surprising ways. We're also pretty against adding configuration for niche features.

@vegansk
Copy link
Author

vegansk commented Dec 27, 2019

But these caveats are well known for that who uses namespaces, and it's really works in babel. And here is a good description of the reasons of using namespaces:

Complex business fat clients like SPA may contain a lot types in different namespaces. ES module is not going to replace namespaces of TS, since module is 1 to 1 mapping with file. Manually avoiding circular references among files is a nightmare against application programming and overall productivity of app programmers. Namepaces is the best solution for code generation -- all generated by code generator stay in one file.

Our simplified example of using namespaces from real business application. Without namespaces it becomes a naming hell.

// ADT Route

export type Route = Route.Main | Route.Reports | Route.Report

export namespace Route {
  /* Главная страница */
  export interface Main {__tag: "Main"}

  /* Список отчетов */
  export interface Reports {__tag: "Reports"}

  /* Отчет */
  export interface Report {
    __tag: "Report"
    info: ReportInfo
  }
}

export namespace Route {
  export const Main = (): Route => {return {__tag: "Main"}}

  export const Reports = (): Route => {return {__tag: "Reports"}}

  export const Report = (info: ReportInfo): Route => {
    return {
      __tag: "Report",
      info
    }
  }
}

@heyimalex
Copy link
Contributor

I think you could do that like this:

type Route = Route.Main | Route.Reports | Route.Report;

declare namespace Route {
  export interface Main {
    __tag: "Main";
  }
  export interface Reports {
    __tag: "Reports";
  }
  export interface Report {
    __tag: "Report";
    info: ReportInfo;
  }
}

const Route = {
  Main: (): Route => ({ __tag: "Main" }),
  Reports: (): Route => ({ __tag: "Reports" }),
  Report: (info: ReportInfo): Route => ({ __tag: "Report", info })
};

export default Route;

That being said, I'm kind of open to this? The problem I'm trying to prevent is code that appears to compile fine, but breaks at runtime. I'm honestly skeptical that the caveats are well known, but maybe isolatedModules plus uninitialized variable lints make this a non-issue. Will have to play around with it to see.

@vegansk
Copy link
Author

vegansk commented Jan 16, 2020

I refactored our code generator to support suggested pattern, it works well. Thank you

@vegansk vegansk closed this as completed Jan 16, 2020
@lock lock bot locked and limited conversation to collaborators Jan 24, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants