Skip to content

Commit cf2eb5f

Browse files
guscastroNoNameProvided
authored andcommitted
fix: ensure [] | undefined union types defaults to array on transform
1 parent dff2aff commit cf2eb5f

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

src/TransformOperationExecutor.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ClassTransformOptions } from "./ClassTransformOptions";
22
import { defaultMetadataStorage } from "./storage";
3-
import { TypeHelpOptions, Discriminator, TypeOptions } from "./metadata/ExposeExcludeOptions";
3+
import { TypeHelpOptions, TypeOptions } from "./metadata/ExposeExcludeOptions";
44
import { TypeMetadata } from "./metadata/TypeMetadata";
55

66
export enum TransformationType {
@@ -37,7 +37,7 @@ export class TransformOperationExecutor {
3737
level: number = 0) {
3838

3939
if (Array.isArray(value) || value instanceof Set) {
40-
const newValue = arrayType && this.transformationType === TransformationType.PLAIN_TO_CLASS ? new (arrayType as any)() : [];
40+
const newValue = arrayType && this.transformationType === TransformationType.PLAIN_TO_CLASS ? instantiateArrayType(arrayType) : [];
4141
(value as any[]).forEach((subValue, index) => {
4242
const subSource = source ? source[index] : undefined;
4343
if (!this.options.enableCircularCheck || !this.isCircular(subValue)) {
@@ -402,3 +402,11 @@ export class TransformOperationExecutor {
402402
}
403403

404404
}
405+
406+
function instantiateArrayType (arrayType: Function): Array<any> | Set<any> {
407+
const array = new (arrayType as any)();
408+
if (!(array instanceof Set) && !("push" in array)) {
409+
return [];
410+
}
411+
return array;
412+
}

test/functional/basic-functionality.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,4 +1738,33 @@ describe("basic functionality", () => {
17381738
transformedClass.should.be.instanceOf(TestClass);
17391739
});
17401740

1741+
it("should default union types where the plain type is an array to an array result", () => {
1742+
class User {
1743+
name: string;
1744+
}
1745+
1746+
class TestClass {
1747+
@Type(() => User)
1748+
usersDefined: User[] | undefined;
1749+
1750+
@Type(() => User)
1751+
usersUndefined: User[] | undefined;
1752+
}
1753+
1754+
const obj = Object.create(null);
1755+
obj.usersDefined = [{ name: "a-name" }];
1756+
obj.usersUndefined = undefined;
1757+
1758+
const transformedClass = plainToClass(TestClass, obj as Object);
1759+
1760+
transformedClass.should.be.instanceOf(TestClass);
1761+
1762+
transformedClass.usersDefined.should.be.instanceOf(Array);
1763+
transformedClass.usersDefined.length.should.equal(1);
1764+
transformedClass.usersDefined[0].should.be.instanceOf(User);
1765+
transformedClass.usersDefined[0].name.should.equal("a-name");
1766+
1767+
expect(transformedClass.usersUndefined).to.equal(undefined);
1768+
});
1769+
17411770
});

0 commit comments

Comments
 (0)