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

Interproject References in tsconfig.json #3394

Closed
nycdotnet opened this issue Jun 5, 2015 · 5 comments
Closed

Interproject References in tsconfig.json #3394

nycdotnet opened this issue Jun 5, 2015 · 5 comments

Comments

@nycdotnet
Copy link

I've been thinking about project-level modularization with TypeScript, and I think the story is not nearly as good as what's available in other Microsoft languages like C# or VB. TypeScript urges you to have everything in a single folder structure (and in VS within a single project) and if you want to break out of that structure, the cost is time spent writing manual scripts to copy definitions around (and figuring out how to even get those definitions if using external modules), and then waiting for those scripts to run before having to run a full compile.

Visual Studio has a great solution for this when using .NET : interproject references. They're easy to set up and work great. If I have a .NET project with a client EXE, a server EXE, and a shared logic DLL, when I change the DLL, both the client and the server EXE projects know immediately and will show type errors via the language services - even before I've actually compiled the modified DLL. I'm yearning for such an experience in TypeScript.

I think that there may be a solution (pun intended) to this in TypeScript and it lies in allowing interproject references to be specified in the tsconfig.json file. Here is my idea:

"projectReferences": {
   "MyOtherProject1": ["../MyOtherProject1/tsconfig.json","external/MyOtherProject1.d.ts"],
   "MyOtherProject2": ["../MyOtherProject2/tsconfig.json","external/MyOtherProject2.d.ts"]
}

The proposed projectReferences tag in tsconfig.json would be an object with named properties that are string arrays. Each property's value would be a series of fallback pointers to a file on disk relative to the tsconfig.json. The first element in each array that is found would be added to the compilation context for the current project only; the rest are ignored. If none are found, it is a compile error such as "Failed to resolve project reference for 'MyOtherProject1'.".

With this example tsconfig.json:

  • If I have MyOtherProject1 cloned to my computer, then the files referenced by that project's tsconfig.json are added to my current project's compilation context.
  • If I don't have MyOtherProject2 cloned to my computer, then the d.ts file that I've provided would be added to the compilation context instead. If that d.ts file is not found, it is a compiler error.

For me, this functionality (or something like it) would significantly improve the TypeScript modularization story and decrease the amount of plumbing I have to write to get different dependent modules in different folder structures compiling together.

@kitsonk
Copy link
Contributor

kitsonk commented Jun 5, 2015

It think there is a subtle challenge here, especially when comparing to other things like C# or VB. The problem is that the common-currency in built TypeScript "packages" (e.g. EcmaScript) is something that is npm or bower based and even then.

I think there is a way to improve the "packaging" of TypeScript, but in lots of ways it would then try to enforce a new paradigm onto others that might be dependent on other types of packaging. So I think in a way, TypeScript hasn't really been able to address packaging without breaking/affecting lots of other things.

Right now, there is a gap in bringing an entire TypeScript toolchain together and in lots of cases, there is still a dependency on native EcmaScript packages in any complex project (of where DefinatelyTyped and tsd come in) and there is also the dts-generator to build your definitions.

Right now, the way Dojo 2 is approaching packaging is to try to get a situation where you can depend upon TypeScript based modules a bit more seamlessly and generate something that can then be built and pulled into your project. There are still gaps in it, but as you can see, there is a lot to the toolchain that is external to TypeScript and getting all of what you need into the baseline of TypeScript reduce options. No one has been able to agree over the years on packaging for EcmaScript/JavaScript. TypeScript, I think at this point, doesn't have a prayer of being able to tackle that right now.

@nycdotnet
Copy link
Author

I agree with you that JS packaging is an enormous subject. I haven't looked at Dojo 2, but what you've said is interesting. This proposal is solely intended to provide a way to augment how TypeScript arrives at its compilation context in a manner that is compatible with how people currently tend to develop JS packages (for consumption via npm or otherwise) using TypeScript.

@nycdotnet
Copy link
Author

To explicitly state the real-world example that I'm thinking of:

The TypeStrong project grunt-ts depends on csproj2ts. Normal users get both of these projects via npm as plain JavaScript modules.

It would be great if I could add something like this to the tsconfig.json of grunt-ts.

"projectReferences": {
   "csproj2ts": ["../csproj2ts/tsconfig.json","node_modules/csproj2ts/csproj2ts.d.ts"],
}

What I would expect from this:

  • For a developer who (like me) has csproj2ts cloned to the relative ../csproj2ts/ folder, TypeScript would add anything referenced by that tsconfig.json file to the compilation context when compiling grunt-ts. It wouldn't emit anything for csproj2ts - it'd just consider it for compilation purposes. If I made a change to the csproj2ts project, a language service evaluating grunt-ts would react immediately - that's the win here.
  • For a developer who didn't have csproj2ts there, it would just fall back to the csproj2ts.d.ts file that came along the last time the package was fetched and everything would work identically to how things work today if the d.ts file were simply included in the list of files to compile.

Things that are out of scope for this suggestion:

  • Building using the tsconfig.json of grunt-ts would not cause the csproj2ts project to also build/emit JS. This proposal is just for supplementing the compilation context.
  • It'd still be the developer's responsibility to update fallback definition files in dependent repositories, if necessary or desired. (TypeScript would never auto-update the node_modules/csproj2ts/csproj2ts.d.ts file in grunt-ts, for example).
  • This has no impact on the emitted JS or its runtime behavior with regards to resolving modules. If (for example) someone were working on grunt-ts and didn't run npm install so that the csproj2ts JS file were there, it would still fail. This is a TypeScript compile-time feature only.

An obvious short-coming of this proposal is that it would still fall on the developer to copy emitted JS files as necessary to make their code work at runtime - this is still a smaller burden than the current system, and could perhaps be handled with additional external tooling or some sort of other tsconfig.json extension to allow running arbitrary scripts at build time (similar to the scripts tag in package.json, which would also be cool).

@NoelAbrahams
Copy link

@nycdotnet,

Request #2180 has a suggestion for setting up a VS project structure using internal modules. What do you think of that? There is no copying of files involved. There are some missing features that I outlined in a comment, But in practice we have achieved good project-level modularisation.

For external modules we use NTVS. NTVS has npm integration.

@nycdotnet
Copy link
Author

@NoelAbrahams Thanks for replying. I think that sounds like a good solution for projects using internal modules in VS. I have been tracking NTVS for more than a year, but always uninstalled it because it felt too unstable with TypeScript. Is the latest version fairly solid? Does that help you link to external modules hosted in external projects, or do you still have to generate and copy around d.ts files?

I suspect you'll be interested in #3469 which sounds like it may be implementing something like #2180, but via tsconfig.json rather than in the Visual Studio project properties. I'm going to close this request for now and post in #3469 only. Thanks again for replying!

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants