typescript - 通过字符串属性名称对属性进行打字稿类型安全更新
问题描述
我需要通过字符串属性名称更新类的属性值。我首先通过此方法确保属性名称有效:
export class ClientDTO {
...
static isValidPropertyName(name: string): name is keyof ClientDTO {
return (name as keyof ClientDTO) !== undefined
}
}
然后在另一堂课上,我正在这样做:
foo(key: string, newValue: string) {
if (!ClientDTO.isValidPropertyName(key)) {
return
}
if (newValue !== this.originalClient[key]) {
// @ts-ignore
this.originalClient[key] = newValue
}
}
查找现在运行良好,但要进行更新,我必须把它放在// @ts-ignore
那里,我真的很想弄清楚如何正确地做到这一点,而不必在那里忽略。
我打开了严格的检查,所以我得到了错误
TS2322:类型“任何”不可分配给类型“从不”
解决方案
问题是您的自定义类型保护:
isValidPropertyName(name: string): name is keyof ClientDTO { ... }
正在防范 的任何键ClientDTO
,因此当您尝试使用它时:
this.originalClient[key] = newValue // newValue is type string
TypeScript 试图推断this.originalClient[key]
. 由于key
可以是的任何键ClientDTO
,因此您分配给它的值必须可分配给这些键的所有值类型。由于这些键的值类型混合在一起,因此唯一可以分配给它们的类型是底部类型never
;无法为其分配任何内容的类型,因此会出现错误。
要解决此问题,请注意您提供newValue
type string
。因此,将您的类型保护限制为只有那些ClientDTO
谁的值是字符串的键:
type KeysWithStringValues<T extends {}> = {
[K in keyof T]: T[K] extends string ? K : never;
}[keyof T];
class ClientDTO {
/* ... */
static isValidPropertyName(name: string): name is KeysWithStringValues<ClientDTO> {
// Make sure to replace this with code that ACTUALLY enforces
// the above constraint.
return name !== undefined
}
}
推荐阅读
- gradle - 如何构建 Minecraft ClientAPI
- pure-js - 使用纯js从数组中删除不是数字的元素
- azure-blob-storage - Azure blob 容器安装到 AKS 部署错误
- python - 每次另一个另一个进程更新文件时如何从文件中读取
- node.js - 如何自动识别日期格式
- generics - 不拥有的泛型参数的生命周期范围
- javascript - 如何刷新翻译以响应短语应用程序
- python - 在 Visual Studio 2019 中导入 python 包的问题
- python - 计算字符串 Python 中的总元音或辅音
- vuetify.js - 如何使 vuetify v-menu 项目可使用 tab 键导航