Могу ли я назначить 2 разных типа для интерфейсов машинописи? - PullRequest
0 голосов
/ 11 апреля 2020

У меня следующая структура интерфейса для хранения путешественников.

interface Person: {
    age: number,
    name: string
}

interface TravelersDirectory {
    [country: string]: Person[]
}
example:
    travelersDirectory = {
        'India': [
            {
                age: 30,
                name 'X'
            },
            {
                age: 35,
                name 'Y'
            },
        ]
    }

С новым изменением я собираюсь отделить людей от каталога путешественников до Людей, а ссылки будут храниться в каталоге путешественников. Новый интерфейс будет выглядеть следующим образом:

interface Persons extends Array<Person>

Но из-за бизнес-требований путешественники могут хранить в индексе (Persons) или объекте Person

пример:

    const persons = [
            {
                age: 30,
                name 'X'
            },
            {
                age: 35,
                name 'Y'
            },
        ];

    const travelersDirectory = [
        'India': [
            0,
            {
                age: 35,
                name 'Y'
            },              
        ]
    ]

Это возможно? оба типа (индекс и объект Person) могут сосуществовать? Я попытался отработать, внеся изменения в интерфейс travelDirectory, но он не сработал. Попытка 1:

    interface TravelersDirectory {
        [country: string]: Person[] | number[]
    }

Попытка 2:

    interface Persons extends Array<Person | number>

    interface TravelersDirectory {
        [country: string]: Persons
    }

Как я могу это сделать?

Примечание. Используемая структура данных имеет символьную c, и я могу ' т редизайн это. Обойти это можно, только играя с интерфейсами

Проверьте эту ссылку на точную проблему https://stackblitz.com/edit/typescript-ypc59j

Ответы [ 2 ]

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

Вторая попытка в вопросе - это правильный способ напечатать это, но его можно упростить до этого:

interface TravelersDirectory {
  [country: string]: Array<Person | number>;
}

После некоторой перемотки с OP, я обнаружил, что проблема была где-то еще, ie этот код:

function getName(travelersDirectory: TravelersDirectory, country: string, index: number) {
  return travelersDirectory[country][index].name;
}

Это потому, что travelersDictionary[country][index] может быть либо Person, либо числом, поэтому свойство name не гарантируется. Чтобы это исправить, нам нужно защититься от этого и определить, что должно произойти, если результатом travelersDictionary[country][index] является число. Мы можем сделать это, сохранив результат в переменной и используя typeof, чтобы проверить, является ли результат числом, прежде чем мы сообщим ему, что произойдет, если это будет Person.

function getName(travelersDirectory: TravelersDirectory, country: string, index: number) {
    const person = travelersDirectory[country][index];
    if (typeof person === "number") {
      // getName was called referencing a number instead of a Person. 
      // Throw Error? Do nothing? Up to you
      throw Error("Can't get name of a number");
    } else {
      // Typescript is smart enough to understand that the variable `person` can't be a number
      // (because we guarded against it in the previous if-expression)
      // so now we can do person.name
      return person.name;
    }
}

Вот Stackblitz демонстрирующий это

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

Исходя из ваших требований, самое простое решение - просто сослаться на возможные значения в самом TravelersDirectory:

interface TravelersDirectory {
    [country: string]: Array<Person | number>;
}

Если вы хотите, чтобы его было легче читать, вы также можете использовать псевдонимы типов:

type PersonID = number;
type Persons = Array<Person | PersonID>;

interface TravelersDirectory {
    [country: string]: Persons
}

Лично я считаю, что наиболее удобочитаемым является использование псевдонима типа для идентификатора и объявление каталога следующим образом:

type PersonID = number;

interface TravelersDirectory {
    [country: string]: Array<Person | PersonID>;
}

Это также позволяет позднее изменить идентификатор пользователя на что-то еще как объект или строка вместо числа, если это необходимо.

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