Skip to content

Instantly share code, notes, and snippets.

@kendallroth
Last active July 10, 2025 21:25
Show Gist options
  • Select an option

  • Save kendallroth/bc19d823113a2d27b6b9167bdbbd1f76 to your computer and use it in GitHub Desktop.

Select an option

Save kendallroth/bc19d823113a2d27b6b9167bdbbd1f76 to your computer and use it in GitHub Desktop.
Update TypeORM entity fields from a NestJS DTO object
/**
* 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