首页 > 解决方案 > 设置对象各个属性的函数的正确类型?

问题描述

我有一个设置对象,它有几个不同类型的不同属性。我正在尝试编写如下函数:

update(settings, name, value)

更新属性name并将settings其设置为value. 我的实际用例有点不同,但这是问题的最简单版本。

我无法让 Typescript 理解我想在这里做什么,它抱怨我的代码:

interface ISettings {
  string_setting: string;
  boolean_setting: boolean;
}

function updateSettings(
  oldSettings: ISettings,
  name: keyof ISettings,
  value: ISettings[keyof ISettings]
): ISettings {
  let newSettings: ISettings = { ...oldSettings };
  newSettings[name] = value;
  return newSettings;
}

在线上

  newSettings[name] = value;

我收到错误

键入'字符串 | boolean' 不能分配给类型 'never'。类型“字符串”不可分配给类型“从不”.ts(2322)

VSCode 告诉我它newSettings属于 ISettings 类型,并且name属于“string_setting”类型 | “布尔设置”。所以这看起来应该是这样,但仍然会引发错误。

我认为for 的类型value也不正确,因为它只是设置对象上属性的所有可能类型的联合,它不能确保值类型与 name 参数选择的特定属性匹配。

为什么 Typescript 在我的代码中抱怨“从不”?输入我描述的函数的正确方法是什么,理想情况下如此严格以至于尝试将字符串分配给布尔设置会失败?

标签: typescript

解决方案


翻译成简单的英文,签名

function updateSettings(
  oldSettings: ISettings,
  name: keyof ISettings,
  value: ISettings[keyof ISettings]
)

说:

  • name是一个属性的名称ISettings
  • value是一个属性的值ISettings

但并没有说它在两种情况下都是相同的属性,让调用者可以自由编写:

updateSettings(isettings, "string_property", true);

...这就是为什么函数体中的属性分配不知道类型是否正确,并被编译器拒绝的原因。

相比之下,签名

updateSettings<K extends keyof ISettings>(
  oldSettings: ISettings,
  name: K,
  value: ISettings[K]
)

表示在这样的键中只有一个类型,既是类型,又是类型。KISettingsnameKvalueISettings[K]


推荐阅读