Skip to content

Commit c289145

Browse files
committed
feat: add type arguments in transform decorator
1 parent a2734a5 commit c289145

File tree

4 files changed

+44
-5
lines changed

4 files changed

+44
-5
lines changed

sample/sample6-type-arguments/app.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { plainToInstance, Transform } from '../../src';
2+
3+
interface CSVInvoiceRecord {
4+
net: string;
5+
}
6+
7+
class Invoice {
8+
@Transform<CSVInvoiceRecord, 'net', number>(({ value }) => Number(value.replace(',', '')))
9+
net: number;
10+
}
11+
12+
const rawInvoice: CSVInvoiceRecord = {
13+
net: '2,000',
14+
};
15+
16+
const invoice = plainToInstance(Invoice, rawInvoice);
17+
console.log(invoice);

src/decorators/transform.decorator.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import { TransformFnParams, TransformOptions } from '../interfaces';
66
*
77
* Can be applied to properties only.
88
*/
9-
export function Transform(
10-
transformFn: (params: TransformFnParams) => any,
9+
export function Transform<T extends Record<string, any> = any, K extends keyof T = any, R = any>(
10+
transformFn: (params: TransformFnParams<T, K>) => R,
1111
options: TransformOptions = {}
1212
): PropertyDecorator {
1313
return function (target: any, propertyName: string | Symbol): void {
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { TransformationType } from '../../enums';
22
import { ClassTransformOptions } from '../class-transformer-options.interface';
33

4-
export interface TransformFnParams {
5-
value: any;
4+
export interface TransformFnParams<T extends Record<string, any> = any, K extends keyof T = any> {
5+
value: T[K];
66
key: string;
7-
obj: any;
7+
obj: T;
88
type: TransformationType;
99
options: ClassTransformOptions;
1010
}

test/functional/custom-transform.spec.ts

+22
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,28 @@ describe('custom transformation decorator', () => {
783783
}).not.toThrow();
784784
});
785785

786+
it('should serialize json to invoice instance of class Invoice with type arguments', () => {
787+
defaultMetadataStorage.clear();
788+
expect(() => {
789+
interface CSVInvoiceRecord {
790+
net: string;
791+
}
792+
793+
class Invoice {
794+
@Transform<CSVInvoiceRecord, 'net', number>(({ value }) => Number(value.replace(',', '')))
795+
net: number;
796+
}
797+
798+
const rawInvoice: CSVInvoiceRecord = {
799+
net: '2,000',
800+
};
801+
802+
const invoice = plainToInstance(Invoice, rawInvoice);
803+
expect(invoice).toBeInstanceOf(Invoice);
804+
expect(invoice.net).toEqual(2000);
805+
}).not.toThrow();
806+
});
807+
786808
it('should serialize a model into json', () => {
787809
expect(() => {
788810
instanceToPlain(model);

0 commit comments

Comments
 (0)