Skip to content

Commit d2ba760

Browse files
authored
feat: set default value if nothing provided (#381)
1 parent dff90ca commit d2ba760

File tree

4 files changed

+79
-9
lines changed

4 files changed

+79
-9
lines changed

src/TransformOperationExecutor.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -294,14 +294,19 @@ export class TransformOperationExecutor {
294294
// Apply the default transformation
295295
finalValue = this.transform(subSource, finalValue, type, arrayType, isSubValueMap, level + 1);
296296
} else {
297-
finalValue = this.transform(subSource, subValue, type, arrayType, isSubValueMap, level + 1);
298-
finalValue = this.applyCustomTransformations(
299-
finalValue,
300-
targetType as Function,
301-
transformKey,
302-
value,
303-
this.transformationType
304-
);
297+
if (subValue === undefined && this.options.exposeDefaultValues) {
298+
// Set default value if nothing provided
299+
finalValue = newValue[newValueKey];
300+
} else {
301+
finalValue = this.transform(subSource, subValue, type, arrayType, isSubValueMap, level + 1);
302+
finalValue = this.applyCustomTransformations(
303+
finalValue,
304+
targetType as Function,
305+
transformKey,
306+
value,
307+
this.transformationType
308+
);
309+
}
305310
}
306311

307312
if (newValue instanceof Map) {

src/interfaces/class-transformer-options.interface.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,10 @@ export interface ClassTransformOptions {
5757
* DEFAULT: `false`
5858
*/
5959
enableImplicitConversion?: boolean;
60+
61+
/**
62+
* If set to true then class transformer will take default values for unprovided fields.
63+
* This is useful when you convert a plain object to a class and have an optional field with a default value.
64+
*/
65+
exposeDefaultValues?: boolean;
6066
}

test/functional/basic-functionality.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
plainToClassFromExist,
99
} from '../../src/index';
1010
import { defaultMetadataStorage } from '../../src/storage';
11-
import { Exclude, Expose, Type } from '../../src/decorators';
11+
import { Exclude, Expose, Type, Transform } from '../../src/decorators';
1212

1313
describe('basic functionality', () => {
1414
it('should convert instance of the given object to plain javascript object and should expose all properties since its a default behaviour', () => {
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { Expose, plainToClass, Transform } from '../../src';
2+
3+
describe('expose default values', () => {
4+
class User {
5+
@Expose({ name: 'AGE' })
6+
@Transform(({ value }) => parseInt(value, 10))
7+
age: number;
8+
9+
@Expose({ name: 'AGE_WITH_DEFAULT' })
10+
@Transform(({ value }) => parseInt(value, 10))
11+
ageWithDefault?: number = 18;
12+
13+
@Expose({ name: 'FIRST_NAME' })
14+
firstName: string;
15+
16+
@Expose({ name: 'FIRST_NAME_WITH_DEFAULT' })
17+
firstNameWithDefault?: string = 'default first name';
18+
19+
@Transform(({ value }) => !!value)
20+
admin: boolean;
21+
22+
@Transform(({ value }) => !!value)
23+
adminWithDefault?: boolean = false;
24+
25+
lastName: string;
26+
27+
lastNameWithDefault?: string = 'default last name';
28+
}
29+
30+
it('should set default value if nothing provided', () => {
31+
const fromPlainUser = {};
32+
const transformedUser = plainToClass(User, fromPlainUser, { exposeDefaultValues: true });
33+
34+
expect(transformedUser).toBeInstanceOf(User);
35+
expect(transformedUser).toEqual({
36+
age: undefined,
37+
ageWithDefault: 18,
38+
firstName: undefined,
39+
firstNameWithDefault: 'default first name',
40+
adminWithDefault: false,
41+
lastNameWithDefault: 'default last name',
42+
});
43+
});
44+
45+
it('should take exposed values and ignore defaults', () => {
46+
const fromPlainUser = {};
47+
const transformedUser = plainToClass(User, fromPlainUser);
48+
49+
expect(transformedUser).toBeInstanceOf(User);
50+
expect(transformedUser).toEqual({
51+
age: NaN,
52+
ageWithDefault: NaN,
53+
firstName: undefined,
54+
firstNameWithDefault: undefined,
55+
adminWithDefault: false,
56+
lastNameWithDefault: 'default last name',
57+
});
58+
});
59+
});

0 commit comments

Comments
 (0)