Все свойства объекта имеют разные ключи, но имеют одинаковый тип - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть объект, используемый только один раз, с тремя свойствами, но каждое свойство должно быть одного типа.Следующее работает для меня, но мне интересно, есть ли более эффективный способ объявления типа для timingsObject:

  let timingsObject:
     { start: null | string, end: null | string, length: null | string } =
     { start: null, end: null, length: null }

  // ... later on timeingsArray is of string[] type
  timingsObject.start = timingsArray[0];
  timingsObject.end = timingsArray[1];
  timingsObject.length = timingsArray[2];

Ответы [ 3 ]

0 голосов
/ 07 февраля 2019

Плохо

Вы могли бы определить свою форму как

interface Timings {
  start: string | null;
  end: string | null;
  length: string | null;
}

, но этот дизайн не может правильно выразить вашу проблему.Например, { start: string, end: null, length: null } является правильным на уровне типа, но представляет недопустимое состояние в вашей программе.

Если мы должны были сделать:

if (timingsObject.start) {
  typeof timingsObject.length.toString(); // Compile-type error!
}

мы знаем, что timingsObject.length являетсястрока, но TypeScript нет.Прежде чем можно будет использовать любое другое свойство timingsObject, его необходимо проверить как первое string.

Хорошо

Смоделируйте вашу проблему как суммудвух государств.Первый четко определен:

interface Timings {
    start: string;
    end: string;
    length: string;
}

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

declare const timings: Empty<Timings> | Timings;

Как мы моделируем Empty?Давайте сделаем это отображаемым типом, который превращает все в null.

type Empty<T> =
  T extends object
    ? { [K in keyof T]: null }
    : null

declare function isEmpty<T>(argument: T | Empty<T>): argument is Empty<T>;

Теперь компилятор знает, что если одно свойство является строкой, то любое другое свойство также является строкой.

if (!isEmpty(timings)) {
  timings.start + timings.end; // Both are known to be strings!
}

Это решение может выглядеть как потраченная работа (и оно есть), но оно успешно превращает проблему вашего домена в систему типов.

0 голосов
/ 11 февраля 2019

Поскольку все свойства объекта тайминга будут либо строкой, либо ложными (и фактически не используются в этом состоянии), и поскольку все свойства применяются только в одном месте, мы также можем:

interface Timings {
    start: string;
    end: string;
    length: string;
}

let timings?: Timings; // could also use let timings: Timings | null = null;

// do other things ...

timings = {
    start: "someValue",
    end: "someOtherValue,
    length: "yetAnotherValue"
};
0 голосов
/ 07 февраля 2019

Я могу придумать два альтернативных способа сделать это.Общий тип или предопределенный тип.

interface IObject<T> {
  start: T
  end: T
  length: T
}

type myType = string | null

interface IObject2 {
  start: myType
  end: myType
  length: myType
}

let timingsObject: IObject<string | null> = { start: null, end: null, length: null }
let timingsObject: IObject2 = { start: null, end: null, length: null }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...