Приведение интерфейса к словарю - PullRequest
0 голосов
/ 17 января 2019

У меня есть функция logNumbers, которая принимает словарь, в котором все ключи являются строками, а все значения являются числами. Я хочу вызвать logNumbers, если объект принадлежит более строгому интерфейсу, но все еще удовлетворяет этим условиям.

interface NumberDictionary {
  [key: string]: number;
}

interface StatisticsResult {
  mean: number;
  mode: number;
  median: number;
}

function logNumbers(numDict: NumberDictionary) { ... }

const results: StatisticsResult = {
  mean: 1,
  mode: 2,
  median: 2,
};

// 
// Error:
//   Argument of type 'StatisticsResult' is not assignable to parameter of type 'NumberDictionary'.
//   Index signature is missing in type 'StatisticsResult'.
//
logNumbers(results);

Я бы хотел, чтобы StatisticsResult остался прежним и каким-то образом изменить подпись для logNumbers. Есть ли способ сделать это? Возможно, я мог бы дать понять, что никакие новые ключи не будут добавлены к numDict в пределах logNumbers?

Воспроизведение на площадке TypeScript

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Если ваша цель состоит в том, чтобы ограничить функцию объектом только с числовыми свойствами, вы можете использовать параметр общего типа, ограниченный, чтобы быть записью только с числами.

  interface StatisticsResult {
    mean: number;
    mode: number;
    median: number;
  }

  function logNumbers<T extends Record<keyof T, number>>(num: T) {
    // Log the numbers as a table or something
  }

  const results: StatisticsResult = {
    mean: 1,
    mode: 2,
    median: 2,
  };

  //ok
  logNumbers(results);
0 голосов
/ 17 января 2019

Все, что вам нужно сделать здесь:

interface StatisticsResult extends NumberDictionary {
  mean: number;
  mode: number;
  median: number;
}

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

Вы также можете привести results, хотя это гораздо более хакерски, поскольку сначала нужно привести к unknown (если вы этого не сделаете, ts пожалуется, что ваши типы не перекрываются из-за индекса признак несоответствия) и вид поражения цели:

logNumbers((results as unknown) as NumberDictionary);

И, наконец, хотя вы и сказали, что не хотите изменять StatisticalResult, вы также можете определить сигнатуру индекса (что, как я понимаю, также отрицает цель иметь ваш тип NumberDictionary в любом случае:

interface StatisticsResult{
  [key: string]: number;
  mean: number;
  mode: number;
  median: number;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...