Generi c маппер с использованием Typescript - PullRequest
0 голосов
/ 08 апреля 2020

Вариант использования здесь, например, отображает ответ выборки с результатом json в более сложный класс с использованием обобщений.

Например, mapper<T,U>(U json), где T - ожидаемый тип возвращаемого значения. И U необязательно является классом json.

U может быть массивом, например, приводящим к отображению T[] или Array<T>.

Например, заданный класс User:

class User {
  id: string;
  birthDate: Date;
  name: string;
  adress: CustomAdressImplementation
}

пример json UserJson:

[
  {
    "id": 1,
    "birthdate": "2020-02-20T10:00:19.145Z"
    "name": "Leanne Graham"
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "Gwenborough",
      "zipcode": "92998-3874",
      "geo": {
        "lat": "-37.3159",
        "lng": "81.1496"
      }
    },
  },
  [... more users] 
]

Один из способов пользовательского сопоставления заключается в создании метода сопоставления:

export function mapUser(json: UserJson): User {
  return {
    id: json.id.toString(),
    birthDate: new Date(json.birthdate),
    name: json.name,
    orderLines: mapAddress(json.address),
  };
}

export function mapUserList(json: UserJson[]): User[] {
  if (json) return json.map(mapUser);
  return [];
}

Есть ли более элегантный способ создания набора правил для сопоставления этого с использованием обобщений? Или ручное настраиваемое сопоставление - путь к go при торговле машинописью сложных карт сопоставления c.

В моем примере Date преобразование строк и сопоставление с классом адресов выглядят так, как будто их можно было бы написать более элегантно, избегая стандартного метода отображения Mapper.

Использование библиотеки преобразователя классов не является приемлемым решением, в поисках чистой реализации Typescript с использованием обобщений.

Допущения:

  • Функции реализации адреса и отображения можно предположить, что он совпадает с json, точка рекурсивно сопоставляется с классом

1 Ответ

0 голосов
/ 08 апреля 2020

Вы можете создать mapList функцию, которая выводит переданный маппер:

// Some UserJson type
type UserJson = {
  [key: string]: any;
};

// User type
type User = {
  id: string;
  birthDate: Date;
  name: string;
  orderLines: any;
};

// All mappers should receive a json of type T and return a type U
interface Mapper<T, U> {
  (json: T): U;
}

// We decalre the mapper of user, should receive a UserJson (T) and returns an User (U)
type mapUser = Mapper<UserJson, User>;

function mapUser(json: UserJson): User {
  return {
    id: json.id.toString(),
    birthDate: new Date(json.birthdate),
    name: json.name,
    orderLines: json.address
  };
}

// mapList receives a Mapper<T, U> and returns a function with type (json: T[]) => U[]
function mapList<T, U>(mapper: Mapper<T, U>): (json: T[]) => U[] {
  return (json: T[]): U[] => {
    if (json) return json.map(mapper);
    return [];
  };
}

// As mapList received a Mapper<UserJson, User>, it will return (json: UserJson[]) => User[]
const mapUserList = mapList(mapUser);

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...