ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • class-transformer 사용시 plainToInstance 메서드 사용시 주의할점
    Nest.js/class-transformer 2024. 7. 7. 16:48
    728x90

    TestEntity

    @Entity({ name: 'test' })
    export class TestEntity {
    	@PrimaryGeneratedColumn()
    	id!: number;
    
    	@Column({
    		name: 'content',
    		type: 'text',
    	})
    	content!: string;
    
    	@Column({
    		type: 'timestamptz',
    		transformer: new LocalDateTimeTransformer(),
    		nullable: true,
    	})
    	orderDateTime!: LocalDateTime;
    
    	@Transform(
    		({ value }: { value: Date }) => {
    			console.log('*******호출!!!******');
    			return value.toISOString();
    		},
    		{
    			toPlainOnly: true,
    		},
    	)
    	@CreateDateColumn({
    		type: 'timestamptz',
    	})
    	createdAt!: Date;
    
    	@UpdateDateColumn({
    		type: 'timestamptz',
    	})
    	updatedAt!: Date;
    
    	get CreatedAt() {
    		return ConverDateTime.toLocalDateTime(this.createdAt);
    	}
    
    	get UpdatedAt() {
    		return ConverDateTime.toLocalDateTime(this.updatedAt);
    	}
    }

     

    service.ts

    async test() {
        const now = LocalDateTime.now(); // yyyy-MM-dd
    
        const newDate = this.testRepository.create({
            content: 'hello',
            orderDateTime: now,
        });
    
        const success = await this.testRepository.insert(newDate);
    
        const result = await this.testRepository.findOneOrFail({
            where: {
                id: success.identifiers[0].id,
            },
        });
    
        const entity = plainToInstance(UsersResDto, result.createdAt);
    
        const newEntity = new UsersResDto();
        newEntity.createdAt = result.createdAt;
    
        console.log(entity instanceof UsersResDto); // false
        console.log(newEntity instanceof UsersResDto); // true
        return entity;
    }

     

    해당 코드는 plainToInstance를 활용하여 UsersResDto라는 클래스로 변환하는데 newEntity는 당연히 new 키워드로 생성한 UsersResDto의 인스턴스이니까 instanceof로 확인하면 True가 나오지만 plainToInstance로 변환한 entity는 false가 나온다. 정말 당황스럽지 않을 수 없다. 타입체커 환경에서는 entity는 분명 UserResDto로 추론된다.

    UsersResDto로 추론된다

     

    하지만 entity는 UsersResDto의 인스턴스가 아니다. plainToInstance의 ts 스팩을 확인 해도 예측하기 어렵다.

     

    export declare function plainToInstance<T, V>(cls: ClassConstructor<T>, plain: V[], options?: ClassTransformOptions): T[];
    export declare function plainToInstance<T, V>(cls: ClassConstructor<T>, plain: V, options?: ClassTransformOptions): T;

     

    결론부터 말하자면 plainToInstance에 2번째 인자값에는 {} object 즉, 객체가 와야 한다.

     

    async test() {
        const now = LocalDateTime.now(); // yyyy-MM-dd
    
        const newDate = this.testRepository.create({
            content: 'hello',
            orderDateTime: now,
        });
    
        const success = await this.testRepository.insert(newDate);
    
        const result = await this.testRepository.findOneOrFail({
            where: {
                id: success.identifiers[0].id,
            },
        });
    
    	// 이렇게 사용해야 인스턴스로 변환 된다
        const entity = plainToInstance(UsersResDto, {
            createdAt: result.createdAt,
        });
    
        const newEntity = new UsersResDto();
        newEntity.createdAt = result.createdAt;
    
        console.log(entity instanceof UsersResDto); // true
        console.log(newEntity instanceof UsersResDto); // true
        return entity;
    }

     

     

    728x90
Designed by Tistory.