Skip to content

Commit bcef7eb

Browse files
authored
Always emit Object type in decorator metadata for import type (#56594)
1 parent 2514a64 commit bcef7eb

6 files changed

+137
-7
lines changed

src/compiler/checker.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48312,28 +48312,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4831248312
isTypeOnly = !!rootValueSymbol?.declarations?.every(isTypeOnlyImportOrExportDeclaration);
4831348313
}
4831448314
const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, location);
48315-
const resolvedSymbol = valueSymbol && valueSymbol.flags & SymbolFlags.Alias ? resolveAlias(valueSymbol) : valueSymbol;
48315+
const resolvedValueSymbol = valueSymbol && valueSymbol.flags & SymbolFlags.Alias ? resolveAlias(valueSymbol) : valueSymbol;
4831648316
isTypeOnly ||= !!(valueSymbol && getTypeOnlyAliasDeclaration(valueSymbol, SymbolFlags.Value));
4831748317

4831848318
// Resolve the symbol as a type so that we can provide a more useful hint for the type serializer.
48319-
const typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location);
48320-
if (resolvedSymbol && resolvedSymbol === typeSymbol) {
48319+
const typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, location);
48320+
const resolvedTypeSymbol = typeSymbol && typeSymbol.flags & SymbolFlags.Alias ? resolveAlias(typeSymbol) : typeSymbol;
48321+
48322+
// In case the value symbol can't be resolved (e.g. because of missing declarations), use type symbol for reachability check.
48323+
if (!valueSymbol) {
48324+
isTypeOnly ||= !!(typeSymbol && getTypeOnlyAliasDeclaration(typeSymbol, SymbolFlags.Type));
48325+
}
48326+
48327+
if (resolvedValueSymbol && resolvedValueSymbol === resolvedTypeSymbol) {
4832148328
const globalPromiseSymbol = getGlobalPromiseConstructorSymbol(/*reportErrors*/ false);
48322-
if (globalPromiseSymbol && resolvedSymbol === globalPromiseSymbol) {
48329+
if (globalPromiseSymbol && resolvedValueSymbol === globalPromiseSymbol) {
4832348330
return TypeReferenceSerializationKind.Promise;
4832448331
}
4832548332

48326-
const constructorType = getTypeOfSymbol(resolvedSymbol);
48333+
const constructorType = getTypeOfSymbol(resolvedValueSymbol);
4832748334
if (constructorType && isConstructorType(constructorType)) {
4832848335
return isTypeOnly ? TypeReferenceSerializationKind.TypeWithCallSignature : TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue;
4832948336
}
4833048337
}
4833148338

4833248339
// We might not be able to resolve type symbol so use unknown type in that case (eg error case)
48333-
if (!typeSymbol) {
48340+
if (!resolvedTypeSymbol) {
4833448341
return isTypeOnly ? TypeReferenceSerializationKind.ObjectType : TypeReferenceSerializationKind.Unknown;
4833548342
}
48336-
const type = getDeclaredTypeOfSymbol(typeSymbol);
48343+
const type = getDeclaredTypeOfSymbol(resolvedTypeSymbol);
4833748344
if (isErrorType(type)) {
4833848345
return isTypeOnly ? TypeReferenceSerializationKind.ObjectType : TypeReferenceSerializationKind.Unknown;
4833948346
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
a.ts(1,22): error TS2307: Cannot find module 'unknown-module' or its corresponding type declarations.
2+
3+
4+
==== ./a.ts (1 errors) ====
5+
import { List } from 'unknown-module';
6+
~~~~~~~~~~~~~~~~
7+
!!! error TS2307: Cannot find module 'unknown-module' or its corresponding type declarations.
8+
export type MyList = List<number>;
9+
10+
==== ./b.ts (0 errors) ====
11+
import { type MyList } from './a';
12+
13+
declare var Decorator: any;
14+
15+
class Foo {
16+
@Decorator myList?: MyList;
17+
}
18+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//// [tests/cases/compiler/decoratorMetadataTypeOnlyImport.ts] ////
2+
3+
//// [a.ts]
4+
import { List } from 'unknown-module';
5+
export type MyList = List<number>;
6+
7+
//// [b.ts]
8+
import { type MyList } from './a';
9+
10+
declare var Decorator: any;
11+
12+
class Foo {
13+
@Decorator myList?: MyList;
14+
}
15+
16+
17+
//// [a.js]
18+
"use strict";
19+
Object.defineProperty(exports, "__esModule", { value: true });
20+
//// [b.js]
21+
"use strict";
22+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
23+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
24+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
25+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
26+
return c > 3 && r && Object.defineProperty(target, key, r), r;
27+
};
28+
var __metadata = (this && this.__metadata) || function (k, v) {
29+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
30+
};
31+
Object.defineProperty(exports, "__esModule", { value: true });
32+
var Foo = /** @class */ (function () {
33+
function Foo() {
34+
}
35+
__decorate([
36+
Decorator,
37+
__metadata("design:type", Object)
38+
], Foo.prototype, "myList", void 0);
39+
return Foo;
40+
}());
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//// [tests/cases/compiler/decoratorMetadataTypeOnlyImport.ts] ////
2+
3+
=== ./a.ts ===
4+
import { List } from 'unknown-module';
5+
>List : Symbol(List, Decl(a.ts, 0, 8))
6+
7+
export type MyList = List<number>;
8+
>MyList : Symbol(MyList, Decl(a.ts, 0, 38))
9+
>List : Symbol(List, Decl(a.ts, 0, 8))
10+
11+
=== ./b.ts ===
12+
import { type MyList } from './a';
13+
>MyList : Symbol(MyList, Decl(b.ts, 0, 8))
14+
15+
declare var Decorator: any;
16+
>Decorator : Symbol(Decorator, Decl(b.ts, 2, 11))
17+
18+
class Foo {
19+
>Foo : Symbol(Foo, Decl(b.ts, 2, 27))
20+
21+
@Decorator myList?: MyList;
22+
>Decorator : Symbol(Decorator, Decl(b.ts, 2, 11))
23+
>myList : Symbol(Foo.myList, Decl(b.ts, 4, 11))
24+
>MyList : Symbol(MyList, Decl(b.ts, 0, 8))
25+
}
26+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//// [tests/cases/compiler/decoratorMetadataTypeOnlyImport.ts] ////
2+
3+
=== ./a.ts ===
4+
import { List } from 'unknown-module';
5+
>List : any
6+
7+
export type MyList = List<number>;
8+
>MyList : List<number>
9+
10+
=== ./b.ts ===
11+
import { type MyList } from './a';
12+
>MyList : any
13+
14+
declare var Decorator: any;
15+
>Decorator : any
16+
17+
class Foo {
18+
>Foo : Foo
19+
20+
@Decorator myList?: MyList;
21+
>Decorator : any
22+
>myList : List<number>
23+
}
24+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// @experimentalDecorators: true
2+
// @emitDecoratorMetadata: true
3+
4+
// @filename: ./a.ts
5+
import { List } from 'unknown-module';
6+
export type MyList = List<number>;
7+
8+
// @filename: ./b.ts
9+
import { type MyList } from './a';
10+
11+
declare var Decorator: any;
12+
13+
class Foo {
14+
@Decorator myList?: MyList;
15+
}

0 commit comments

Comments
 (0)