We're using lerna for managing a typescript mono-repo and vscode for editing. Often times vscode will auto-import a type from a sibling package via import something from '../package2' rather than import something from 'package2'. This bypasses tslint's no-implicit-dependencies rule and is definitely not the intended way to import code from a mono-repo. Does tslint have ways to guard against that?
I don't know of any existing TSLint rules for monorepos.
I have written such a rule for internal use within my linter (monorepo) project: https://github.com/fimbullinter/wotan/blob/master/packages/disir/src/rules/import-package.ts
This rule currently resolves the import and checks if .../packages/<name>/... is the same for the importing and the imported file.
I also have a rule to prevent importing from package1 from files inside package1 (though that's already covered by no-implicit-dependencies) with an autofixer to import from the declaring module instead.
Caveats:
It doesn't work with TSLint, it's intended for the use in the Wotan linter runtime.
It's currently not configurable, you can see for example that the scope @fimbul/ is hard coded in the rule.
The directory structure probably also need to be configurable to be really useful.
Wotan currently has no VSCode plugin. You will therefore not see these green squiggles while you type. Instead you need to execute it from the command line.
So if you are OK with using another linter (in addition), please open an issue in my repo and tell a bit about the directory structure in your monorepo. I will then refactor this internal rule and publish it.
Otherwise you can use the code of my rule and port it to your own custom rule for TSLint.
Hi there,
It would appear that this issue is not directly related to a bug or feature request. We request that you use StackOverflow to ask questions about tslint, and tslint rules. Going to close this issue, but please feel free to re-open if you think this is a bug.
Thanks,
TSLint Team
@tonyxiao I'd be very interested to see if you found a solution for this. My team and I are also using a monorepo in this way that you've suggested. So automatically bringing in includes from the adjacent repos should be a warning at least.
I think this is a valid rule request, re-opening and adjusting the title
Possible overlap with #3980?
@JoshuaKGoldberg I don't think it's an overlap. More importantly, the new rule (https://github.com/palantir/tslint/pull/4318) that I made is designed to be more declarative about which folders in the monorepo are actually workspaces.
@tonyxiao please feel free to review that PR so you can let me know if it works for your needs. However, I don't believe that it is exactly what you need because (I believe) you're asking to not let developers include the path of the other workspaces. For that scenario, I bet that https://github.com/palantir/tslint/pull/3504 is going to be the correct solution since you can just put a regex in that puts your workspace folders on a blacklist. But please not that importBlacklistRule still allows nested folders, which is where my new rule has lots of value because you can prevent the following problem:
Let's say we have a section of the code that abstracts away the database access:
// in file "src/workspaces/businessLayerWorkspace/mongoHelpers.ts"
export function getSomethingFromTheDatabase()
But you don't want the UI to be monkeying around with Mongo. Wouldn't it be great if the import below fails? Well it will with PR https://github.com/palantir/tslint/pull/4318 :)
// in file "src/workspaces/userInterfaceWorkspace/uiControllers.ts"
import * as mongoHelpers from "src/workspaces/businessLayerWorkspace/mongoHelpers.ts"
export function getSomethingFromTheDatabase()
And the best part of the new noWorkspacePollutionRule is that it doesn't require Lerna or any monorepo setup at all. You can start putting fences around your various concerns without too much setup.
Re-posting from #4318: There hasn't been a solid proposal for exactly how to solve the issue. We'd need to see a few areas fleshed out in the issue's discussions, such as:
import-package, and should it be?It seems like this rule could go a lot of different ways, and before TSLint itself commits to a single interpretation of how to fix the issue, there should be some consensus from the community.
Yes @JoshuaKGoldberg, I think a comparison would be useful. I have been following the various threads related that are trying to solve separation of concerns and I think that this is pretty good comparative analysis:


I'll now detail how I arrived at the above conclusions:
"prevents importing a nested module from another workspace relatively."
"does fencing in JS as well"
"does not break tslint from running"
"usable without having to employ monorepo solution"
"the fences are configurable"
"It's currently not configurable, you can see for example that the scope @fimbul/ is hard coded in the rule. The directory structure probably also need to be configurable to be really useful.""declarative (i.e. here is my workspace vs. imperatively telling to restrict)"
[true,
{
workspaceEntryPoint: "entrypoint.ts",
workspaceName: "workspaceNumOne",
},{
workspaceEntryPoint: "entrypoint.ts",
workspaceName: "workspaceNumTwo",
}
]
"stays in sync with folder structure due to nested config files (ala fences.json)"
"feedback within vscode"
"correctly allows standard "pathless" imports from node_modules"
"easy configuration"
import-package rule was too cold (from a configuration perspective)."does not require changes to your TypeScript transpilation build process"
Thank you everyone for any and all feedback. :)
Still soliciting community review on my above ^ summary of the current state of "fencing". Anyone else want to weigh in? @ericanderson / @tonyxiao / @JoshuaKGoldberg / @adidahiya
I am about to start using TS project references internally and I would like to get an understanding of how the world works with them before I am able to make a comment. My current guess is:
Since Typescript has native references (monorepo) support, and you're obviously not supposed to import with a relative path outside the current package, I don't see why anyone would be opposed to this rule? This as well as references support (#4137) is what's lacking in tslint in our case.
The ts-import-zones rule from https://github.com/vladimiry/tslint-rules-bunch may address some of the usecases here. Not as full featured as some of the other solutions but definitely a good starting point if you need something now.
~also consider https://github.com/sverweij/dependency-cruiser~
edit: nvm, it doesn't handle this issue very well right now
The points made earlier this year are fantastic and the use case is certainly valid... but not many folks have seemed interested in this rule yet _(perhaps it's a bit ahead of its time?)_, and TSLint is being deprecated: #4534. I'd suggest bring this issue up in typescript-eslint.
Thanks for the discussions, folks! I'm hopeful the code in #4318 ends up being used by the community in some way - either as a standard ESLint rule or within the new core ruleset.
Most helpful comment
Yes @JoshuaKGoldberg, I think a comparison would be useful. I have been following the various threads related that are trying to solve separation of concerns and I think that this is pretty good comparative analysis:


I'll now detail how I arrived at the above conclusions:
"It's currently not configurable, you can see for example that the scope @fimbul/ is hard coded in the rule. The directory structure probably also need to be configurable to be really useful."import-packagerule was too cold (from a configuration perspective).Thank you everyone for any and all feedback. :)