How to prevent one project import internal modules from another project?
Problem
Suppose I have two projects structured like this:
├── proj_1 │ ├── hidden │ │ └── hidden-class.mts │ ├── index.mts │ ├── visible-class.mts │ └── tsconfig.json └── proj_2 ├── main.mts └── tsconfig.json |
The tsconfig.json of proj_1 is:
{ "compilerOptions": { "rootDir": ".", "baseUrl": ".", "target": "ESNext", "module": "ESNext", "moduleResolution": "node", "composite": true // build proj_1 as a lib }, "references": [], "include": ["*", "**/*"], } |
And the one for proj_2:
{ "compilerOptions": { "rootDir": ".", "baseUrl": ".", "target": "ESNext", "module": "ESNext", "moduleResolution": "node", "composite": true, "paths": { // I only want to expose a single file from proj_1 to proj_2 "~/proj_1/index.mjs": ["../proj_1/index.mjs"] } }, "references": [ { // path mapping "path": "../proj_1/" } ], "include": ["*", "**/*"], } |
Then I found I could write such code, which is not expected:
// proj_1/index.mts // Only export `VisibleClass` and other project should only import this file. export { VisibleClass } from "./visible-class.mjs";
// proj_2/main.mts import { VisibleClass } from "~/proj_1/index.mjs"; // This line should be error. How do I prevent this path from importing? import { HiddenClass } from "../proj_1/hidden/hidden-class.mjs";
const v = new VisibleClass();
// This line should be error const h = new HiddenClass(); |
As the code tells I don't want the HiddenClass to be exported but it could actually. I don't know how to prevent that.
Solution
tsconfig.json references are for "make the implementation files unable to import the test files of the same package".
If you have a lib and an app this most likely should be different packages in a monorepo
Here's roughly how that could look like:
{ "name": "vue", "main": "index.js", "module": "dist/vue.runtime.esm-bundler.js", "types": "dist/vue.d.ts", "exports": { ".": { "import": { "types": "./dist/vue.d.mts", "node": "./index.mjs", "default": "./dist/vue.runtime.esm-bundler.js" }, "require": { "types": "./dist/vue.d.ts", "default": "./index.js" } }, "./server-renderer": { "import": { "types": "./server-renderer/index.d.mts", "default": "./server-renderer/index.mjs" }, "require": { "types": "./server-renderer/index.d.ts", "default": "./server-renderer/index.js" } }, }, "dependencies": { "@vue/shared": "workspace:*" } } |
exports will limit what you are able to import {} from 'vue/....' in this case
You may check >https://github.com/vuejs/core/tree/main/packages/vue or >https://github.com/rhyek/typescript-monorepo-example for an example of TS monorepo
Suggested blogs:
>Why Typescript does not allow a union type in an array?
>Narrow SomeType vs SomeType[]
>Create a function that convert a dynamic Json to a formula in Typescript
>How to destroy a custom object within the use Effect hook in TypeScript?
>How to type the values of an object into a spreadsheet in TypeScript?
>Type key of record in a self-referential manner in TypeScript?
>How to get the last cell with data for a given column in TypeScript?
>Ignore requests by interceptors based on request content in TypeScript?
>Create data with Typescript Sequelize model without passing in an id?
>How to delete duplicate names from Array in Typescript?