Last active
July 10, 2025 21:25
-
-
Save kendallroth/bc19d823113a2d27b6b9167bdbbd1f76 to your computer and use it in GitHub Desktop.
Update TypeORM entity fields from a NestJS DTO object
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Set defined/scalar entity fields from a DTO (only using fields existing on entity) | |
| * | |
| * NOTE: Mutates original value! | |
| * | |
| * NOTE: Skips all non-scalar fields and `undefined` DTO values, which would other wise cause unexpected | |
| * data loss for non-specified or partially provided relation values. However, non-scalar fields | |
| * can be permitted with `allowNonScalarKeys` if specifically handled/provided. | |
| * | |
| * @param options.allowNonScalarKeys - Allows non-scalar keys to be assigned (ie. arrays, objects, etc) | |
| * @param options.omitKeys - Keys to omit from assigning to entity (ie. ids, etc) | |
| * @param options.onlyKeys - Keys to allow assigning to entity (skips others if specified!) | |
| * | |
| * @returns Entity with updated scalar fields | |
| * | |
| * @example | |
| * const supplier = await this.supplierRepo.findOne({where: {id}}); | |
| * setEntityFieldsFromDto(supplier, payload, {omitKeys: ["id"]}); | |
| * supplier = await this.supplierRepo.save(supplier); | |
| */ | |
| export const setEntityFieldsFromDto = <T extends BaseEntity>( | |
| entity: T, | |
| dto: ClassInstance, | |
| options: { | |
| allowNonScalarKeys?: (keyof T)[]; | |
| omitKeys?: (keyof T)[]; | |
| onlyKeys?: (keyof T)[]; | |
| } = {}, | |
| ): T => { | |
| const {omitKeys, onlyKeys} = options; | |
| Object.keys(entity).forEach((key) => { | |
| const entityKey = key as keyof typeof entity; | |
| const entityValue = entity[entityKey]; | |
| const dtoValue = dto[entityKey as string]; | |
| // Skip entity properties missing from DTO object, specifically omitted keys, or non-whitelisted keys (if whitelisting) | |
| if ( | |
| dtoValue === undefined || | |
| omitKeys?.includes(entityKey) || | |
| (onlyKeys && !onlyKeys.includes(entityKey)) | |
| ) { | |
| return; | |
| } | |
| // Skip non-scalar values (to avoid incorrect replacements/merges), unless specified with 'allowNonScalarKeys' | |
| if ( | |
| isArray(entityValue) || | |
| isArray(dtoValue) || | |
| (isObject(entityValue) && !(entityValue instanceof Date)) || | |
| (isObject(dtoValue) && !(dtoValue instanceof Date)) | |
| ) { | |
| // Ensure that only allowed non-scalar keys that are actually set on DTO will update the entity! | |
| if (!options.allowNonScalarKeys?.includes(entityKey) || dtoValue === undefined) { | |
| return; | |
| } | |
| } | |
| entity[entityKey] = dtoValue as typeof entityValue; | |
| }); | |
| return entity; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment