Skip to content

Commit bcf7bf1

Browse files
fix: support excludeExtraneousValues option with ignoreDecorators enabled
1 parent 3491beb commit bcf7bf1

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

src/TransformOperationExecutor.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,16 @@ export class TransformOperationExecutor {
426426
return keys;
427427
}
428428

429+
/**
430+
* If decorators are ignored but we don't want the extraneous values, then we use the
431+
* metadata to decide which property is needed, but doesn't apply the decorator effect.
432+
*/
433+
if (this.options.ignoreDecorators && this.options.excludeExtraneousValues && target) {
434+
const exposedProperties = defaultMetadataStorage.getExposedProperties(target, this.transformationType);
435+
const excludedProperties = defaultMetadataStorage.getExcludedProperties(target, this.transformationType);
436+
keys = [...exposedProperties, ...excludedProperties];
437+
}
438+
429439
if (!this.options.ignoreDecorators && target) {
430440
// add all exposed to list of keys
431441
let exposedProperties = defaultMetadataStorage.getExposedProperties(target, this.transformationType);

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ export interface ClassTransformOptions {
1212

1313
/**
1414
* Indicates if extraneous properties should be excluded from the value when converting a plain value to a class.
15+
*
16+
* This option requires that each property on the target class has at least one `@Expose` or `@Exclude` decorator
17+
* assigned from this library.
1518
*/
1619
excludeExtraneousValues?: boolean;
1720

@@ -33,8 +36,10 @@ export interface ClassTransformOptions {
3336
excludePrefixes?: string[];
3437

3538
/**
36-
* If set to true then class transformer will ignore all @Expose and @Exclude decorators and what inside them.
39+
* If set to true then class transformer will ignore the effect of all @Expose and @Exclude decorators.
3740
* This option is useful if you want to kinda clone your object but do not apply decorators affects.
41+
*
42+
* __NOTE:__ You may still have to add the decorators to make other options work.
3843
*/
3944
ignoreDecorators?: boolean;
4045

test/functional/basic-functionality.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,40 @@ describe('basic functionality', () => {
118118
expect(transformedUserWithoutExtra).not.toHaveProperty('age');
119119
});
120120

121+
it('should exclude extraneous values if both excludeExtraneousValues and ignoreDecorators option is set to true', () => {
122+
// fixes https://github.com/typestack/class-transformer/issues/533
123+
defaultMetadataStorage.clear();
124+
125+
class ExampleClass {
126+
@Exclude()
127+
public valueOne!: number;
128+
129+
@Expose()
130+
public valueTwo!: number;
131+
}
132+
133+
const transformationOptions = {
134+
ignoreDecorators: true,
135+
excludeExtraneousValues: true,
136+
};
137+
138+
const instance = plainToClass(
139+
ExampleClass,
140+
{ valueOne: 42, valueTwo: 42, extra: true, _otherExtra: true },
141+
transformationOptions
142+
);
143+
144+
expect(instance).toBeInstanceOf(ExampleClass);
145+
expect(instance).toEqual({ valueOne: 42, valueTwo: 42 });
146+
147+
(instance as any).extraProp = 'not-needed';
148+
149+
expect(classToPlain(instance, transformationOptions)).toEqual({
150+
valueOne: 42,
151+
valueTwo: 42,
152+
});
153+
});
154+
121155
it('should exclude all objects marked with @Exclude() decorator', () => {
122156
defaultMetadataStorage.clear();
123157

0 commit comments

Comments
 (0)