在 Typescript 中,当从可能未定义的字典中获取记录时,您应该使用类型断言吗?

In Typescript should you use type assertion when taking a record from a dictionary that could have been undefined?

字典通常用于通过字符串标识符有效地测试元素是否存在。如果结果是 undefined 它不存在。内存缓存就是一个很好的例子:

/**
 * Cache of normalized data
 */
export interface IDataNormalizationsCache
  extends Record<NormalizationMethod, ILeanTrainingData | undefined> {}

/**
 * A dictionary which caches all performed varieties of data normalizations.
 */
const dataNormalizations: IDataNormalizationsCache = {
  [NormalizationMethod.log]: undefined
}

然后我们可以从缓存中检索此数据:

// Retrieve from cache
if (typeof dataNormalizations[method] !== 'undefined') {
  return dataNormalizations[method]
}

然而,即使 dataNormalizations[method] 保证在此时定义,因此属于 ILeanTrainingData 类型,Typescript 也会抛出编译错误:

[ts]
Type 'ILeanTrainingData | undefined' is not assignable to type 'ILeanTrainingData'.
  Type 'undefined' is not assignable to type 'ILeanTrainingData'.

为什么编译器不识别 typeof undefined 测试?

有没有比使用类型断言更好的方法,例如:

// Retrieve from cache
if (typeof dataNormalizations[method] !== 'undefined') {
  return dataNormalizations[method] as ILeanTrainingData
}

这是 an outstanding issue in TypeScript 的可悲后果,即 属性 通过括号表示法访问不会像使用点表示法那样触发类型保护。显然,向编译器添加对括号符号的检查很简单,但会导致编译时间显着延长。

我假设您在编译时不知道 属性 名称的实际字符串文字......否则我建议使用点表示法:

if (typeof dataNormalizations.knownMethod !== 'undefined') {
  return dataNormalizations.knownMethod; // works
}

它会起作用的。但你可能不能那样做。在这种情况下更好的解决方法是将 属性 分配给一个新变量:

const dataNormalizationsMethod = dataNormalizations[method];
if (typeof dataNormalizationsMethod !== 'undefined') {
  return dataNormalizationsMethod; // works
}

这也允许类型保护工作,因为它不再进行 属性 访问。

在我看来,你的类型断言也很好。

希望对您有所帮助。祝你好运!