microsoft / microsoft/TypeScript
Self-referencing causes non-portable inferred types (TS2742) false positive
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 132
Description
### 🔎 Search Terms
- The inferred type of '...' cannot be named without a reference to '...'. This is likely not portable. A type annotation is necessary.
- TS2742
- Project reference redirect
- Self-reference
- Build mode
- Watcher
### 🕗 Version & Regression Information
Versions 4.7 - 5.9.3.
I've reproduced this in TypeScript 4.7.2, which is when [self-referencing was first announced as a feature](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#packagejson-exports-imports-and-self-referencing). This bug appears on the latest version of TypeScript at the time of writing (i.e. 5.9.3).
### ⏯ Playground Link
This issue requires multiple NPM packages. Small repro at https://github.com/gluxon/typescript-portability-error-false-positive-due-to-self-import
### 💻 Code
I've set up a repro at https://github.com/gluxon/typescript-portability-error-false-positive-due-to-self-import.
The code below is from the repro above and should match exactly. The TypeScript for the repro itself is only ~16 lines of code. In these packages, package `a` depends on `b` + `c`, and package `b` depends on `c`.
```mermaid
graph LR
a --> b
a --> c
b --> c
```
```ts
// packages/a/src/index.ts
import { B } from "b";
const b: B = {
c: { foo: "bar" },
};
export const c = b.c;
```
```ts
// packages/b/src/index.ts
import { C } from "c";
export interface B {
readonly c: C;
}
```
```ts
// packages/c/src/index.ts
export type { C } from "./C";
export type { C2 as C2 } from "./C2";
```
```ts
// packages/c/src/C.ts
export interface C {
readonly foo: "bar";
}
```
```ts
// packages/c/src/C2.ts
// 🚨 This self-reference causes the non-portable type false positive. 🚨
// Importing from "./C" instead of "c" fixes the issue.
import { C } from "c";
export type C2 = C;
```
### 🙁 Actual behavior
When running `tsc` with build mode, a false positive error is shown.
```console
tsc --build --verbose packages/a/tsconfig.json
```
```
[8:40:22 PM] Building project '/Volumes/git/typescript-false-positive-non-portable-watcher-error/packages/a/tsconfig.json'...
packages/a/src/index.ts:7:14 - error TS2742: The inferred type of 'c' cannot be named without a reference to '../node_modules/c/src'. This is likely not portable. A type annotation is necessary.
7 export const c = b.c;
~
```
The error above should not happen since:
1. Running `tsc` without the build flag does not show this issue. (See "_Expected Behavior_" below.)
2. The portability error is non-sensical. It's looking for a reference to package `c`'s source code in `../node_modules/c/src` rather than its built `.d.ts` files. I've narrowed this to a bug with project reference redirects.
3. The portability error happens even when `c` is a dependency of `a`.
### 🙂 Expected behavior
Running `tsc` without the `--build` flag results in a successful compilation of package `a`.
```console
# Compile manually in topological order.
tsc -p packages/c/tsconfig.json
tsc -p packages/b/tsconfig.json
tsc -p packages/a/tsconfig.json
```
### Additional information about the issue
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.