Question:
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?


Nisha Patel

Nisha Patel

Submit
0 Answers