Repository: TypeScript
Issue: Module resolution: tsc unexpectedly rewrites the import path when exports field contains multiple entries resolving to the same file
Labels: Suggestion,Needs Proposal

### 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:
```ts
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 `lru-cache@10.0.1`'s exports field: https://unpkg.com/browse/lru-cache@10.0.1/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/index.d.ts@10.0.1'. ========
======== 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 <i@izs.me>",
  "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!