如何从本地私有模块导入TypeScript声明至应用(Yarn Workspaces)
Let's break down how to fix your module resolution and compilation errors when importing types from package a into package b—no extra JavaScript implementation required. The key is to leverage Yarn Workspaces' linking capabilities and TypeScript's package-based type resolution system properly.
Step 1: Fix Package A's package.json
Since package a is a pure type-only package, you need to explicitly tell TypeScript where to find its type definitions. Update packages/a/package.json with these critical fields:
{ "name": "a", "version": "1.0.0", "private": true, // Mark as private to avoid accidental publishing (essential for workspaces) "types": "index.d.ts" // This tells TypeScript the entry point for type definitions }
Note: You don't need a
mainfield here—mainis for JavaScript entry points, and this package only contains types. Thetypesfield is the correct choice for type-only packages.
Step 2: Verify Root Workspace Configuration
Make sure your root package.json correctly defines the workspaces so Yarn can automatically link your local packages:
{ "private": true, "workspaces": [ "packages/*" // Includes all packages under the packages/ directory ] }
Step 3: Link Package A to Package B via Yarn Workspaces
Run this command from your project root to add package a as a dependency to package b. Yarn will create a symlink in packages/b/node_modules/a pointing directly to packages/a:
yarn workspace b add a
Alternatively, you can manually add the dependency to packages/b/package.json (Yarn will resolve the workspace link automatically):
{ "dependencies": { "a": "workspace:*" } }
Step 4: Adjust Package B's tsconfig.json
Update packages/b/tsconfig.json to ensure TypeScript can resolve the a package correctly. Here's the corrected configuration:
{ // Extend root tsconfig if you have one (optional but recommended for consistent settings) "extends": "../../tsconfig.json", "compilerOptions": { "rootDir": "./src", "outDir": "./build", "baseUrl": ".", // Set base URL to the package b directory "paths": { "a": ["../a"] // Map the "a" package to its local directory }, "moduleResolution": "node", // Ensure Node-style module resolution (default in TS 4.7+) "skipLibCheck": true // Optional: Speed up compilation by skipping type checks for node_modules files }, "include": ["./src/**/*.ts"], // Optional: Use TypeScript Project References for faster incremental builds "references": [{ "path": "../a" }] }
Why Your Previous Attempts Failed
Let's clear up why your earlier approaches didn't work:
- Paths pointing directly to
index.d.ts: TypeScript treats this as a source file, not a package, so it tries to include it in compilation—but since it's outsiderootDir, it throws an error. Using the package directory with atypesfield tells TypeScript to treat it as a type package instead. - Adding
mainto packagea: Themainfield targets JavaScript files, not types. TypeScript was looking for a JS entry point that doesn't exist, leading to confusion. - Including external files in
include: Files outsiderootDircan't be included as source files, which is why adding../../a/index.d.tsdidn't resolve the issue. Package-based resolution avoids this problem entirely.
Testing the Setup
You should now be able to import types from a in packages/b/src/index.ts without errors:
import { Foo } from 'a'; // Use the Foo type as needed const bar: Foo = { /* ... */ };
Run your TypeScript build for package b (e.g., yarn workspace b tsc)—it should compile successfully now.
内容的提问来源于stack exchange,提问作者Draon con Color

