TypeScript generi c сопоставление объекта с объектом сопоставления - PullRequest
1 голос
/ 14 июля 2020

Я пытаюсь создать общую 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]
}

1 Ответ

0 голосов
/ 14 июля 2020

Вы можете использовать охрану типов и утверждать тип как это

function isFunction(val: any): val is () => string {
  return typeof val === "function";
}

function isUndefined(val: any): val is string {
  return typeof val !== "undefined";
}

и использовать его так

function map<S, D>(source: S & { [key: string]: any }, mapper: Mapper<S, D>) {
  const destination: any = {};
  for (const key in mapper) {
    const val = mapper[key];
    if (isFunction(val)) {
      destination[key] = val(source);
    } else if (isUndefined(val)) {
      destination[key] = source[val];
    }
  }
  return destination;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...