TypeScript Type или интерфейс для нормализованных данных

TLDR: как создать интерфейс для нормализованных данных?

Я строю приложение React с использованием TypeScript. Я использую Normalizr для нормализации данных из моих вызовов API.

Чтобы привести пример из документации, ответ API выглядит следующим образом:

Быстрый старт Рассмотрим типичный пост в блоге. Ответ API для одного сообщения может выглядеть примерно так:

{
  "id": "123",
  "author": {
    "id": "1",
    "name": "Paul"
  },
  "title": "My awesome blog post",
  "comments": [
    {
      "id": "324",
      "commenter": {
        "id": "2",
        "name": "Nicole"
      }
    }
  ]
}

Может быть нормализовано к этому:

{
  result: "123",
  entities: {
    "articles": {
      "123": {
        id: "123",
        author: "1",
        title: "My awesome blog post",
        comments: [ "324" ]
      }
    },
    "users": {
      "1": { "id": "1", "name": "Paul" },
      "2": { "id": "2", "name": "Nicole" }
    },
    "comments": {
      "324": { id: "324", "commenter": "2" }
    }
  }
}

Я хотел бы создать интерфейсы для моих функций, которые используют Normalizr. Вот что я пробовал до сих пор:

export interface House {
  uuid: string;
  address: string;
}

export interface Citizen {
  uuid: string;
  name: string;
}

export interface NormalizedData<T> {
  [uuid: string]: T;
}

export interface Entity<T> {
  [name: string]: NormalizedData<T>;
}

export interface NormalizerResult<T> {
  result: any;
  entities: Entity<T>;
}

Поскольку здесь я должен дать общий тип T, этот подход может обрабатывать только одну сущность. Проблема в том, что ключ сущностей может иметь несколько сущностей разных типов, например. Дом и гражданин (и многое другое). Как я могу объяснить это? Собственные типы нормализатора просто отдают { result: any, entities: any },

1 ответ

Решение

Я думаю, вы хотите что-то подобное

export interface NormalizerResult<T extends House | Citizen> {
  result: any;
  entities: Entity<T>;
}

PS Typescript более полезен, когда вы на 100% знаете структуру ответа, и менее полезен, если ответ каждый раз отличается. Если первое правильно, то вы должны сделать типы для каждого ответа, например

export interface NormalizerResultForHousesAndCitizensRequest {
  result: any;
  entities: {
    houses: NormalizedData<House>,
    citizens: NormalizedData<Citizen>,
  };
}
Другие вопросы по тегам