Я пытаюсь создать общую c функцию сопоставления объектов, которая позволила бы мне, например, сопоставить объект сущности с объектом передачи данных. Правила сопоставления будут даны в объекте сопоставления.
Например, при следующем:
class UserEntity {
id: number
userName: string
}
class CustomerDto {
customerNumber: number
name: string
slug: string
}
const mapper = {
customerNumber: 'id',
name: 'userName',
slug: (userEntity: UserEntity) => (
userEntity.userName.toLowerCase().replace(/\s/g, '-')
)
}
свойство id
из UserEntity
будет сопоставлено с customerNumber
на Customer
, от userName
до name
, а свойство slug
будет установлено с использованием данной функции.
Вот мой код:
type FilteredKeys<T, U> = {
[P in keyof T]: T[P] extends U ? P : never
}[keyof T]
type Mapper<S, D> = {
[DK in keyof D]?: ( FilteredKeys<S, D[DK]> ) | ( (source: S) => D[DK] )
}
function map<S, D>(
source: S,
mapper: Mapper<S, D>
) {
const destination: D = {} as D
for (const key in mapper) {
const val = mapper[key]
if (typeof val === 'function') {
destination[key] = val(source)
} else if (typeof val !== 'undefined') {
destination[key] = source[val]
}
}
return destination
}
Полный пример StackBlitz
Есть как минимум два типа проблем, которые я не знаю, как решить:
- Значения свойств объекта сопоставления не могут использоваться в качестве ключей для исходный объект.
- По-видимому, защиты типа недостаточно.
Упрощенная версия ( StackBlitz ), которая поддерживает только функции в картографе, похоже, работает:
type Mapper<S, D> = {
[DK in keyof D]?: (source: S) => D[DK]
}