将接口强制转换为字典



>我有一个函数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的签名。有没有办法做到这一点?也许我可以向打字稿发出信号,表示不会在logNumbers内向numDict添加新键?

在打字稿游乐场中复制

如果您的目标是将函数限制为仅具有数字属性的对象,则可以使用约束为仅包含数字的记录的泛型类型参数。

  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);

您需要做的就是:

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;
}

最新更新