Skip to content

Commit 36ac4eb

Browse files
authored
Fix reference marking of values merged with unresolvable type-only imports (#54799)
1 parent 3a7a4d4 commit 36ac4eb

26 files changed

+512
-54
lines changed

src/compiler/checker.ts

Lines changed: 61 additions & 49 deletions
Large diffs are not rendered by default.

src/compiler/types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3814,8 +3814,8 @@ export type TypeOnlyImportDeclaration =
38143814

38153815
export type TypeOnlyExportDeclaration =
38163816
| ExportSpecifier & ({ readonly isTypeOnly: true } | { readonly parent: NamedExports & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true } } })
3817-
| ExportDeclaration & { readonly isTypeOnly: true } // export * from "mod"
3818-
| NamespaceExport & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true } } // export * as ns from "mod"
3817+
| ExportDeclaration & { readonly isTypeOnly: true, readonly moduleSpecifier: Expression } // export * from "mod"
3818+
| NamespaceExport & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true, readonly moduleSpecifier: Expression } } // export * as ns from "mod"
38193819
;
38203820

38213821
export type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration;
@@ -5878,7 +5878,7 @@ export interface SymbolLinks {
58785878
deferralParent?: Type; // Source union/intersection of a deferred type
58795879
cjsExportMerged?: Symbol; // Version of the symbol with all non export= exports merged with the export= target
58805880
typeOnlyDeclaration?: TypeOnlyAliasDeclaration | false; // First resolved alias declaration that makes the symbol only usable in type constructs
5881-
typeOnlyExportStarMap?: Map<__String, ExportDeclaration & { readonly isTypeOnly: true }>; // Set on a module symbol when some of its exports were resolved through a 'export type * from "mod"' declaration
5881+
typeOnlyExportStarMap?: Map<__String, ExportDeclaration & { readonly isTypeOnly: true, readonly moduleSpecifier: Expression }>; // Set on a module symbol when some of its exports were resolved through a 'export type * from "mod"' declaration
58825882
typeOnlyExportStarName?: __String; // Set to the name of the symbol re-exported by an 'export type *' declaration, when different from the symbol name
58835883
isConstructorDeclaredProperty?: boolean; // Property declared through 'this.x = ...' assignment in constructor
58845884
tupleLabelDeclaration?: NamedTupleMember | ParameterDeclaration; // Declaration associated with the tuple's label

src/testRunner/unittests/services/transpile.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,4 +620,16 @@ export * as alias from './file';`, {
620620
testVerbatimModuleSyntax: true
621621
}
622622
);
623+
624+
transpilesCorrectly("Preserves exported const merged with type-only import", `
625+
import fooValue from "./values";
626+
import type {Foo} from "./types";
627+
628+
const Foo: Foo = fooValue as any as Foo;
629+
630+
export {Foo};
631+
`, {
632+
options: { compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ESNext } },
633+
testVerbatimModuleSyntax: true
634+
});
623635
});

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5832,9 +5832,11 @@ declare namespace ts {
58325832
};
58335833
}) | ExportDeclaration & {
58345834
readonly isTypeOnly: true;
5835+
readonly moduleSpecifier: Expression;
58355836
} | NamespaceExport & {
58365837
readonly parent: ExportDeclaration & {
58375838
readonly isTypeOnly: true;
5839+
readonly moduleSpecifier: Expression;
58385840
};
58395841
};
58405842
type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration;

tests/baselines/reference/api/typescript.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1774,9 +1774,11 @@ declare namespace ts {
17741774
};
17751775
}) | ExportDeclaration & {
17761776
readonly isTypeOnly: true;
1777+
readonly moduleSpecifier: Expression;
17771778
} | NamespaceExport & {
17781779
readonly parent: ExportDeclaration & {
17791780
readonly isTypeOnly: true;
1781+
readonly moduleSpecifier: Expression;
17801782
};
17811783
};
17821784
type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration;

tests/baselines/reference/importElisionExportNonExportAndDefault.symbols

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import MyFunction from "./MyComponent";
55
>MyFunction : Symbol(MyFunction, Decl(main.ts, 0, 6))
66

77
MyFunction({msg: "Hello World"});
8+
>MyFunction : Symbol(MyFunction, Decl(main.ts, 0, 6))
89
>msg : Symbol(msg, Decl(main.ts, 2, 12))
910

1011

tests/baselines/reference/importEquals3.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ exports.A = A;
3333
//// [b.js]
3434
"use strict";
3535
Object.defineProperty(exports, "__esModule", { value: true });
36-
exports.x = void 0;
36+
exports.x = exports.A = void 0;
37+
var A = a.A; // Error
38+
exports.A = A;
3739
var x = 0;
3840
exports.x = x;
3941
//// [c.js]
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery2.ts] ////
2+
3+
//// [z.ts]
4+
interface A {}
5+
export type { A };
6+
7+
//// [a.ts]
8+
import { A } from './z';
9+
const A = 0;
10+
export { A };
11+
export class B {};
12+
13+
//// [b.ts]
14+
import * as types from './a';
15+
let t: typeof types = {
16+
A: undefined as any, // ok
17+
B: undefined as any,
18+
}
19+
20+
21+
//// [z.js]
22+
"use strict";
23+
Object.defineProperty(exports, "__esModule", { value: true });
24+
//// [a.js]
25+
"use strict";
26+
Object.defineProperty(exports, "__esModule", { value: true });
27+
exports.B = exports.A = void 0;
28+
var A = 0;
29+
exports.A = A;
30+
var B = /** @class */ (function () {
31+
function B() {
32+
}
33+
return B;
34+
}());
35+
exports.B = B;
36+
;
37+
//// [b.js]
38+
"use strict";
39+
Object.defineProperty(exports, "__esModule", { value: true });
40+
var t = {
41+
A: undefined,
42+
B: undefined,
43+
};
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery2.ts] ////
2+
3+
=== /z.ts ===
4+
interface A {}
5+
>A : Symbol(A, Decl(z.ts, 0, 0))
6+
7+
export type { A };
8+
>A : Symbol(A, Decl(z.ts, 1, 13))
9+
10+
=== /a.ts ===
11+
import { A } from './z';
12+
>A : Symbol(A, Decl(a.ts, 0, 8), Decl(a.ts, 1, 5))
13+
14+
const A = 0;
15+
>A : Symbol(A, Decl(a.ts, 0, 8), Decl(a.ts, 1, 5))
16+
17+
export { A };
18+
>A : Symbol(A, Decl(a.ts, 2, 8))
19+
20+
export class B {};
21+
>B : Symbol(B, Decl(a.ts, 2, 13))
22+
23+
=== /b.ts ===
24+
import * as types from './a';
25+
>types : Symbol(types, Decl(b.ts, 0, 6))
26+
27+
let t: typeof types = {
28+
>t : Symbol(t, Decl(b.ts, 1, 3))
29+
>types : Symbol(types, Decl(b.ts, 0, 6))
30+
31+
A: undefined as any, // ok
32+
>A : Symbol(A, Decl(b.ts, 1, 23))
33+
>undefined : Symbol(undefined)
34+
35+
B: undefined as any,
36+
>B : Symbol(B, Decl(b.ts, 2, 22))
37+
>undefined : Symbol(undefined)
38+
}
39+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery2.ts] ////
2+
3+
=== /z.ts ===
4+
interface A {}
5+
export type { A };
6+
>A : A
7+
8+
=== /a.ts ===
9+
import { A } from './z';
10+
>A : 0
11+
12+
const A = 0;
13+
>A : 0
14+
>0 : 0
15+
16+
export { A };
17+
>A : 0
18+
19+
export class B {};
20+
>B : B
21+
22+
=== /b.ts ===
23+
import * as types from './a';
24+
>types : typeof types
25+
26+
let t: typeof types = {
27+
>t : typeof types
28+
>types : typeof types
29+
>{ A: undefined as any, // ok B: undefined as any,} : { A: any; B: any; }
30+
31+
A: undefined as any, // ok
32+
>A : any
33+
>undefined as any : any
34+
>undefined : undefined
35+
36+
B: undefined as any,
37+
>B : any
38+
>undefined as any : any
39+
>undefined : undefined
40+
}
41+

0 commit comments

Comments
 (0)