Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/compiler/transformers/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ namespace ts {

const resolver = context.getEmitResolver();
const compilerOptions = context.getCompilerOptions();
const strictNullChecks = typeof compilerOptions.strictNullChecks === "undefined" ? compilerOptions.strict : compilerOptions.strictNullChecks;
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);

Expand Down Expand Up @@ -1869,7 +1870,16 @@ namespace ts {
// Note when updating logic here also update getEntityNameForDecoratorMetadata
// so that aliases can be marked as referenced
let serializedUnion: SerializedTypeNode;
for (const typeNode of node.types) {
for (let typeNode of node.types) {
while (typeNode.kind === SyntaxKind.ParenthesizedType) {
typeNode = (typeNode as ParenthesizedTypeNode).type; // Skip parens if need be
}
if (typeNode.kind === SyntaxKind.NeverKeyword) {
continue; // Always elide `never` from the union/intersection if possible
}
if (!strictNullChecks && (typeNode.kind === SyntaxKind.NullKeyword || typeNode.kind === SyntaxKind.UndefinedKeyword)) {
continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks
}
const serializedIndividual = serializeTypeNode(typeNode);

if (isIdentifier(serializedIndividual) && serializedIndividual.escapedText === "Object") {
Expand All @@ -1893,7 +1903,7 @@ namespace ts {
}

// If we were able to find common type, use it
return serializedUnion;
return serializedUnion || createVoidZero(); // Fallback is only hit if all union constituients are null/undefined/never
}

/**
Expand Down
32 changes: 32 additions & 0 deletions tests/baselines/reference/decoratorMetadataNoStrictNull.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//// [decoratorMetadataNoStrictNull.ts]
const dec = (obj: {}, prop: string) => undefined

class Foo {
@dec public foo: string | null;
@dec public bar: string;
}

//// [decoratorMetadataNoStrictNull.js]
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var dec = function (obj, prop) { return undefined; };
var Foo = /** @class */ (function () {
function Foo() {
}
__decorate([
dec,
__metadata("design:type", String)
], Foo.prototype, "foo");
__decorate([
dec,
__metadata("design:type", String)
], Foo.prototype, "bar");
return Foo;
}());
18 changes: 18 additions & 0 deletions tests/baselines/reference/decoratorMetadataNoStrictNull.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
=== tests/cases/compiler/decoratorMetadataNoStrictNull.ts ===
const dec = (obj: {}, prop: string) => undefined
>dec : Symbol(dec, Decl(decoratorMetadataNoStrictNull.ts, 0, 5))
>obj : Symbol(obj, Decl(decoratorMetadataNoStrictNull.ts, 0, 13))
>prop : Symbol(prop, Decl(decoratorMetadataNoStrictNull.ts, 0, 21))
>undefined : Symbol(undefined)

class Foo {
>Foo : Symbol(Foo, Decl(decoratorMetadataNoStrictNull.ts, 0, 48))

@dec public foo: string | null;
>dec : Symbol(dec, Decl(decoratorMetadataNoStrictNull.ts, 0, 5))
>foo : Symbol(Foo.foo, Decl(decoratorMetadataNoStrictNull.ts, 2, 11))

@dec public bar: string;
>dec : Symbol(dec, Decl(decoratorMetadataNoStrictNull.ts, 0, 5))
>bar : Symbol(Foo.bar, Decl(decoratorMetadataNoStrictNull.ts, 3, 33))
}
20 changes: 20 additions & 0 deletions tests/baselines/reference/decoratorMetadataNoStrictNull.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
=== tests/cases/compiler/decoratorMetadataNoStrictNull.ts ===
const dec = (obj: {}, prop: string) => undefined
>dec : (obj: {}, prop: string) => any
>(obj: {}, prop: string) => undefined : (obj: {}, prop: string) => any
>obj : {}
>prop : string
>undefined : undefined

class Foo {
>Foo : Foo

@dec public foo: string | null;
>dec : (obj: {}, prop: string) => any
>foo : string
>null : null

@dec public bar: string;
>dec : (obj: {}, prop: string) => any
>bar : string
}
2 changes: 1 addition & 1 deletion tests/baselines/reference/metadataOfClassFromAlias.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ var ClassA = /** @class */ (function () {
}
__decorate([
annotation(),
__metadata("design:type", Object)
__metadata("design:type", auxiliry_1.SomeClass)
], ClassA.prototype, "array", void 0);
return ClassA;
}());
Expand Down
16 changes: 8 additions & 8 deletions tests/baselines/reference/metadataOfUnionWithNull.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ var B = /** @class */ (function () {
}
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", String)
], B.prototype, "x");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", Boolean)
], B.prototype, "y");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", String)
], B.prototype, "z");
__decorate([
PropDeco,
Expand All @@ -87,27 +87,27 @@ var B = /** @class */ (function () {
], B.prototype, "c");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", void 0)
], B.prototype, "d");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", typeof Symbol === "function" ? Symbol : Object)
], B.prototype, "e");
__decorate([
PropDeco,
__metadata("design:type", Object)
], B.prototype, "f");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", A)
], B.prototype, "g");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", B)
], B.prototype, "h");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", typeof Symbol === "function" ? Symbol : Object)
], B.prototype, "j");
return B;
}());
8 changes: 8 additions & 0 deletions tests/cases/compiler/decoratorMetadataNoStrictNull.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @experimentalDecorators: true
// @emitDecoratorMetadata: true
const dec = (obj: {}, prop: string) => undefined

class Foo {
@dec public foo: string | null;
@dec public bar: string;
}