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

Proposal for module / namespace behavior to allow class-per-file development approach #15827

Closed
fis-cz opened this issue May 13, 2017 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@fis-cz
Copy link

fis-cz commented May 13, 2017

This is related to #447 but it seems nobody is reading it anymore.

From my perspective, the typescript compiler should do combine same namespaces to the same IIFE, even if its splitted over multiple files. Otherwise its not the same namespace. And its confusing as in real, the 'namespace' keyword is not TypeScript namespace, but JavaScript namespace. Moreover, same named modules splitted over multiple files should be also combined to single output js file to be possible to split AMD, CommonJS or SystemJS module to mutiple files.

I know you are trying to keep as close as possible to ES spec and there is no such possibility to split anything over multiple files but it will be really helpful.

Consider we have a project with the following folder structure:

program
   a
      Ns_a1
         ClassA.ts
         ClassB.ts
      Ns_a1.Ns_a12
         ClassA.ts
      module_exports.ts
   b
      Ns_b1
         tools.ts
      module_exports.ts
   blah.ts
   tsconfig.json

a and b are modules, Ns are namespaces. Export file (module_exports.ts) should be possible to be used as is should be simply possible to define and find out what we are exporting out of the module without need of looking to all files in the module folder structure. Of course, export/reexport of the class, function, namespace or whatever else should be possible from any file in the same module scope, but will be messy in big projects.

The compilation output should be a.js , b.js and blah.js according to definition in files:

module_exports.ts

module a {
   // reexport interface and class B form namespace Ns_a1
   export Ns_a1.I;
   export Ns_a1.B;

   // export whatever else from the module
   export function something() {
   }

   export const blah: string = "blah";

   // of course, it should be possible to export the whole namespace
   export Ns_a1;
}

ClassA.ts:

module a {
   namespace Ns_a1 {
      /* partial */ class A { 
         // class code here, class is not exported so not visible out of Ns_a1
         // for partial proposal see ClassB.ts
      }
   }
}

ClassB.ts:

module a {
   namespace Ns_a1 {

      /* partial */ class A {
         // class merge or Duplicate identifier error
         // I would recommend considering of adopting the "partial" keyword from C#
         // if it would be specified, merge, if not, Duplicate identifier error
      }

      // under normal circumstances, i would place I to separate file but just to shorten the post
      export interface I {
         // exported interface so visible inside module a
      }

      export class B extends A implements I {
         // class code here, class is exported so visible as Ns_a1 inside module a
      }
   }
}

tools.ts

// tools does not define module so nothing to be merged with and works as in the current TS, so
// compiled to separate file (or considered as separate file in case of --out)
namespace Ns_a1 {
   // can't be merged as tools.js is separate module by nature (as it works now)
}

I will not write the code for the b folder branch as it is hopefully clear from previously mentioned code.

Please note the module keyword is supposed to be a AMD, UMD, CommonJS or SystemJS module, not a module pattern from Javascript.

@fis-cz fis-cz changed the title Proposal for module / namespace behavior to allow class-per-namespace development approach Proposal for module / namespace behavior to allow class-per-file development approach May 13, 2017
@fis-cz
Copy link
Author

fis-cz commented May 14, 2017

As I was thinking about it during the night, although it would be very nice and helpful, it would be probably very very hard (I would almost say impossible) to implement.

But what about adding something like

///<include path="file.ts>

directive which would be replaced by the code from the file specified during the compile time?

in such case, we well be able to achieve almost everything, splitting modules per multiple files, splitting namespaces per multiple files, moreover splitting a class over multiple files.

Of course, nothing is ideal and I can see some problems here, such as:

file1.ts

var a = 0;
///<include path="file2.ts" />

file2.ts

console.log(a);

file3.ts

///<include path="file2.ts" />
// should throw a is not defined, but where? here or in the included file? both would be confusing :)

Also, IDE integration could be problematic as it would require to know in what context the the file is included to have the intellisense / type checking available while editing the include file.

But the primary purpose of it should not be reusing of the piece of the code anywhere, so it can be somehow limited, i.e. the given file can be included just once per a program.

Yes, I can use external tool for this. But what about IDE integration? In case of VS there is no possibility how to integrate 3rd party tool to tsbuild process which the language service will take care about as VS extension source is not available. Or is it?

By the way, I think this is only the one problem we are walking around here over multiple issues. It's possible to use 3rd party tools for such cases, I would write a pre/post processors taking care of #IFDEFS, ///<include directive handling, module and namespace merging and whatever else including correct .post-build map file remapping after compilation. This from my perspective correct way how to implement such features while not touching the compiler itself.

But its useless until language service will be able to provide a the complete build info (including 3rd party tools) to IDE.

@mhegazy
Copy link
Contributor

mhegazy commented May 15, 2017

From my perspective, the typescript compiler should do combine same namespaces to the same IIFE, even if its splitted over multiple files. Otherwise its not the same namespace.

How is this different from #447? and why do we need two issues to track the same suggestion?

Moreover, same named modules splitted over multiple files should be also combined to single output js file to be possible to split AMD, CommonJS or SystemJS module to mutiple files.

Please see #17. We have decided to keep modules aligned with what ES6 stipulated. For merging modules, you can use a tool like webpack or browserify to bundle them.

I know you are trying to keep as close as possible to ES spec and there is no such possibility to split anything over multiple files but it will be really helpful.

I would recommend using ES6 modules for these. The pattern i would use us, each component/class/logical unit lives in its own module (i.e. file). in each folder you have collection of modules that belong together, and then add a single entry point, call it index.ts and

export * from "./mod1";
export * from "./mod2";
...

@mhegazy mhegazy added the Duplicate An existing issue was already created label May 15, 2017
@fis-cz
Copy link
Author

fis-cz commented May 16, 2017

How is this different from #447? and why do we need two issues to track the same suggestion?

Its different because it includes two things, modules an namespaces.

Please see #17. We have decided to keep modules aligned with what ES6 stipulated. For merging modules, you can use a tool like webpack or browserify to bundle them.

Although I don't understand your decision so much I I have to live with it. Its probably related to the fact the TypeScript is not working with the project as with real project but rather it compiles each file separately so it would be hard to do it in a different way.

Unfortunately, I didn't find a way how to use mentioned tools in my project but it would be for longer discussion which I don't want to open here.

I would recommend using ES6 modules for these. The pattern i would use us, each component/class/logical unit lives in its own module (i.e. file). in each folder you have collection of modules that belong together, and then add a single entry point, call it index.ts and

So you recommend me to have a separate ES6 module for each file then reexport their exports. This means to have a separate ES6 module for each class and each interface (moreover for additional, supporting code). This also means to have tons of d.ts files. Its not very practical and again it will require some kind of post-build tool to put them together to be usable for the whole module. And export almost everything in internal modules of the module.

@mhegazy
Copy link
Contributor

mhegazy commented May 16, 2017

Its different because it includes two things, modules an namespaces.

Modules and namespaces are two different beasts. we have tried in our early days (hence the use of the same keyword to define both constructs) to consolidate both, and could not make that work. that is why we later on added the keyword namespace to attempt to clear up the confusion.

Any proposal here needs to be clear about what it handles and not lump them together, cause they are not lump-able..

multi-file modules was tracked by #17, and i do not think there is any new information to change this decision.

namespaces are already bundled using --outFile, so what is left it seems is the optimization of compacting them in one closure, and that is tracked by #447.

I would recommend looking into webpacl, browserify, or rollup for bundling options.

So you recommend me to have a separate ES6 module for each file then reexport their exports. This means to have a separate ES6 module for each class and each interface (moreover for additional, supporting code). This also means to have tons of d.ts files. Its not very practical and again it will require some kind of post-build tool to put them together to be usable for the whole module. And export almost everything in internal modules of the module.

Well putting every interface/class/helper function in a file is up to you.
I am not sure i see the problem with file count. if you are writing for node, the number of modules should not rely make a difference, if you are writing for the web, then you have a bundler of sorts, so again not sure why the number of files make a difference here.

@mhegazy
Copy link
Contributor

mhegazy commented Jun 2, 2017

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@mhegazy mhegazy closed this as completed Jun 2, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants