Skip to content

Commit c623408

Browse files
fix: hide implicit type conversion behind a flag.
1 parent 4b3e726 commit c623408

File tree

3 files changed

+57
-22
lines changed

3 files changed

+57
-22
lines changed

src/ClassTransformOptions.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,11 @@ export interface ClassTransformOptions {
6767
* This option is useful when you know for sure that your types might have a circular dependency.
6868
*/
6969
enableCircularCheck?: boolean;
70+
71+
/**
72+
* If set to true then class transformer will try to convert properties implicitly to their target type based on their typing information.
73+
*
74+
* DEFAULT: `false`
75+
*/
76+
enableImplicitConversion?: boolean;
7077
}

src/TransformOperationExecutor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,11 @@ export class TransformOperationExecutor {
199199
this.options.targetMaps
200200
.filter(map => map.target === targetType && !!map.properties[propertyName])
201201
.forEach(map => type = map.properties[propertyName]);
202-
} else if(this.transformationType === TransformationType.PLAIN_TO_CLASS) {
202+
} else if(this.options.enableImplicitConversion && this.transformationType === TransformationType.PLAIN_TO_CLASS) {
203203
// if we have no registererd type via the @Type() decorator then we check if we have any
204204
// type declarations in reflect-metadata (type declaration is emited only if some decorator is added to the property.)
205205
const reflectedType = Reflect.getMetadata("design:type", (targetType as Function).prototype, propertyName);
206-
206+
207207
if (reflectedType) {
208208
type = reflectedType;
209209
}

test/functional/implicit-type-declarations.spec.ts

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,55 @@ import {defaultMetadataStorage} from "../../src/storage";
66
import {Expose, Type} from "../../src/decorators";
77
import {expect} from "chai";
88

9+
describe("implicit type conversion", () => {
10+
it("should run only when enabled", () => {
11+
defaultMetadataStorage.clear();
12+
13+
class SimpleExample {
14+
15+
@Expose()
16+
readonly implicitTypeNumber: number;
17+
18+
@Expose()
19+
readonly implicitTypeString: string;
20+
}
21+
22+
const result1: SimpleExample = plainToClass(SimpleExample, {
23+
implicitTypeNumber: "100",
24+
implicitTypeString: 133123,
25+
}, { enableImplicitConversion: true });
26+
27+
const result2: SimpleExample = plainToClass(SimpleExample, {
28+
implicitTypeNumber: "100",
29+
implicitTypeString: 133123,
30+
}, { enableImplicitConversion: false });
31+
32+
expect(result1).to.deep.equal({ implicitTypeNumber: 100, implicitTypeString: "133123" });
33+
expect(result2).to.deep.equal({ implicitTypeNumber: "100", implicitTypeString: 133123 });
34+
});
35+
});
36+
937
describe("implicit and explicity type declarations", () => {
1038

1139
defaultMetadataStorage.clear();
1240

1341
class Example {
14-
42+
1543
@Expose()
1644
readonly implicitTypeViaOtherDecorator: Date;
1745

1846
@Type()
1947
readonly implicitTypeViaEmptyTypeDecorator: number;
20-
21-
@Type(() => String)
48+
49+
@Type(() => String)
2250
readonly explicitType: string;
2351
}
24-
25-
const result: Example = plainToClass(Example, {
26-
implicitTypeViaOtherDecorator: "2018-12-24T12:00:00Z",
27-
implicitTypeViaEmptyTypeDecorator: "100",
28-
explicitType: 100,
29-
});
52+
53+
const result: Example = plainToClass(Example, {
54+
implicitTypeViaOtherDecorator: "2018-12-24T12:00:00Z",
55+
implicitTypeViaEmptyTypeDecorator: "100",
56+
explicitType: 100,
57+
}, { enableImplicitConversion: true });
3058

3159
it("should use implicitly defined design:type to convert value when no @Type decorator is used", () => {
3260
expect(result.implicitTypeViaOtherDecorator).to.be.instanceOf(Date);
@@ -45,14 +73,14 @@ describe("implicit and explicity type declarations", () => {
4573

4674
});
4775

48-
describe("plainToClass transforms builtin primitive types properly", () => {
76+
describe("plainToClass transforms built-in primitive types properly", () => {
4977

5078
defaultMetadataStorage.clear();
5179

5280
class Example {
5381

5482
@Type()
55-
date: Date;
83+
date: Date;
5684

5785
@Type()
5886
string: string;
@@ -61,27 +89,27 @@ describe("plainToClass transforms builtin primitive types properly", () => {
6189
string2: string;
6290

6391
@Type()
64-
number: number;
92+
number: number;
6593

6694
@Type()
6795
number2: number;
68-
96+
6997
@Type()
7098
boolean: boolean;
71-
99+
72100
@Type()
73101
boolean2: boolean;
74102
}
75-
76-
const result: Example = plainToClass(Example, {
77-
date: "2018-12-24T12:00:00Z",
78-
string: "100",
79-
string2: 100,
103+
104+
const result: Example = plainToClass(Example, {
105+
date: "2018-12-24T12:00:00Z",
106+
string: "100",
107+
string2: 100,
80108
number: "100",
81109
number2: 100,
82110
boolean: 1,
83111
boolean2: 0,
84-
});
112+
}, { enableImplicitConversion: true });
85113

86114
it("should recognize and convert to Date", () => {
87115
expect(result.date).to.be.instanceOf(Date);

0 commit comments

Comments
 (0)