-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
Demo Repo
https://github.com/sodatea/ts-exports-rewrite
Which of the following problems are you reporting?
Something else more complicated which I'll explain in more detail
Demonstrate the defect described above with a code sample.
In the reproduction repo, the parse.ts
file indirectly depends on the lru-cache
module's type by importing the cache.ts
file:
import { createCache } from './cache'
export const parseCache = createCache<{}>()
After compilation, in parse.d.ts
, we would normally expect a import('lru-cache').LRUCache
expression.
However, it actually becomes import("lru-cache/min").LRUCache
.
On the other hand, the compiled cache.d.ts
file still imports from lru-cache
, not lru-cache/min
.
This seems to be related to [email protected]
's exports field: https://unpkg.com/browse/[email protected]/package.json#L34
It contains 2 entries, ./min
and .
, both pointing to the same file. TypeScript picks the first entry.
If I modify the exports
field to make .
appear before ./min
, then the compiled declaration file would use import("lru-cache")
as expected.
While this isn't a very severe bug and has easy workarounds, this is quite unexpected.
Because lru-cache/min
is an entry only available in exports
field, this compilation result breaks the compatibility with older build tools. And it is quite hard to debug, because no documentation ever mentioned that the order of keys in the exports
field would make a difference.
Run tsc --showConfig
and paste its output here
{
"compilerOptions": {
"outDir": "./temp",
"target": "esnext",
"module": "esnext",
"moduleResolution": "bundler",
"esModuleInterop": true,
"declaration": true,
"emitDeclarationOnly": true,
"types": []
},
"files": [
"./cache.ts",
"./parse.ts"
],
"include": [
"cache.ts",
"parse.ts"
],
"exclude": [
"temp"
]
}
Run tsc --traceResolution
and paste its output here
======== Resolving module 'lru-cache' from '/Users/haoqun/Reproductions/ts-exports-rewrite/cache.ts'. ========
Explicitly specified module resolution kind: 'Bundler'.
Resolving in CJS mode with conditions 'import', 'types'.
Found 'package.json' at '/Users/haoqun/Reproductions/ts-exports-rewrite/package.json'.
Loading module 'lru-cache' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Found 'package.json' at '/Users/haoqun/Reproductions/ts-exports-rewrite/node_modules/lru-cache/package.json'.
Entering conditional exports.
Matched 'exports' condition 'import'.
Entering conditional exports.
Matched 'exports' condition 'types'.
Using 'exports' subpath '.' with target './dist/mjs/index.d.ts'.
File '/Users/haoqun/Reproductions/ts-exports-rewrite/node_modules/lru-cache/dist/mjs/index.d.ts' exists - use it as a name resolution result.
Resolved under condition 'types'.
Exiting conditional exports.
Resolved under condition 'import'.
Exiting conditional exports.
Resolving real path for '/Users/haoqun/Reproductions/ts-exports-rewrite/node_modules/lru-cache/dist/mjs/index.d.ts', result '/Users/haoqun/Reproductions/ts-exports-rewrite/node_modules/lru-cache/dist/mjs/index.d.ts'.
======== Module name 'lru-cache' was successfully resolved to '/Users/haoqun/Reproductions/ts-exports-rewrite/node_modules/lru-cache/dist/mjs/index.d.ts' with Package ID 'lru-cache/dist/mjs/[email protected]'. ========
======== Resolving module './cache' from '/Users/haoqun/Reproductions/ts-exports-rewrite/parse.ts'. ========
Explicitly specified module resolution kind: 'Bundler'.
Resolving in CJS mode with conditions 'import', 'types'.
Loading module as file / folder, candidate module location '/Users/haoqun/Reproductions/ts-exports-rewrite/cache', target file types: TypeScript, JavaScript, Declaration, JSON.
File '/Users/haoqun/Reproductions/ts-exports-rewrite/cache.ts' exists - use it as a name resolution result.
======== Module name './cache' was successfully resolved to '/Users/haoqun/Reproductions/ts-exports-rewrite/cache.ts'. ========
Paste the package.json
of the importing module, if it exists
{
"name": "ts-exports-rewrite",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "tsc"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"lru-cache": "10.0.1",
"typescript": "^5.2.2"
}
}
Paste the package.json
of the target module, if it exists
{
"name": "lru-cache",
"description": "A cache object that deletes the least-recently-used items.",
"version": "10.0.1",
"author": "Isaac Z. Schlueter <[email protected]>",
"keywords": [
"mru",
"lru",
"cache"
],
"sideEffects": false,
"scripts": {
"build": "npm run prepare",
"preprepare": "rm -rf dist",
"prepare": "tsc -p tsconfig.json && tsc -p tsconfig-esm.json",
"postprepare": "bash fixup.sh",
"pretest": "npm run prepare",
"presnap": "npm run prepare",
"test": "c8 tap",
"snap": "c8 tap",
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"format": "prettier --write .",
"typedoc": "typedoc --tsconfig tsconfig-esm.json ./src/*.ts",
"benchmark-results-typedoc": "bash scripts/benchmark-results-typedoc.sh",
"prebenchmark": "npm run prepare",
"benchmark": "make -C benchmark",
"preprofile": "npm run prepare",
"profile": "make -C benchmark profile"
},
"main": "./dist/cjs/index.js",
"module": "./dist/mjs/index.js",
"exports": {
"./min": {
"import": {
"types": "./dist/mjs/index.d.ts",
"default": "./dist/mjs/index.min.js"
},
"require": {
"types": "./dist/cjs/index.d.ts",
"default": "./dist/cjs/index.min.js"
}
},
".": {
"import": {
"types": "./dist/mjs/index.d.ts",
"default": "./dist/mjs/index.js"
},
"require": {
"types": "./dist/cjs/index.d.ts",
"default": "./dist/cjs/index.js"
}
}
},
"repository": "git://github.com/isaacs/node-lru-cache.git",
"devDependencies": {
"@size-limit/preset-small-lib": "^7.0.8",
"@types/node": "^20.2.5",
"@types/tap": "^15.0.6",
"benchmark": "^2.1.4",
"c8": "^7.11.2",
"clock-mock": "^1.0.6",
"esbuild": "^0.17.11",
"eslint-config-prettier": "^8.5.0",
"marked": "^4.2.12",
"mkdirp": "^2.1.5",
"prettier": "^2.6.2",
"size-limit": "^7.0.8",
"tap": "^16.3.4",
"ts-node": "^10.9.1",
"tslib": "^2.4.0",
"typedoc": "^0.24.6",
"typescript": "^5.0.4"
},
"license": "ISC",
"files": [
"dist"
],
"engines": {
"node": "14 || >=16.14"
},
"prettier": {
"semi": false,
"printWidth": 70,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"jsxSingleQuote": false,
"bracketSameLine": true,
"arrowParens": "avoid",
"endOfLine": "lf"
},
"tap": {
"coverage": false,
"node-arg": [
"--expose-gc",
"-r",
"ts-node/register"
],
"ts": false
},
"size-limit": [
{
"path": "./dist/mjs/index.js"
}
]
}
Any other comments can go here
Have a nice day!