typescript - 在 TypeScript 中复制相同键属性错误
问题描述
TypeScript 中使用相同的键类型将属性从源复制到目标的正确方法是什么?
interface ITest {
first?(val: number, msg: string): void;
second?(): void
}
function copy(e: keyof ITest, source: ITest, dest: ITest) {
// TS2322:
// Type '(val: number, msg: string) => void' is not assignable to type '() => void'.
dest[e] = source[e];
}
我不明白为什么 TypeScript 看不到源和目标是相同的类型并且我们使用相同的键类型。但是我们应该怎么做呢?
我正在使用 TypeScript 3.6.4,tsconfig.json
如下所示:
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"strict": true
}
解决方案
TS3.5 引入了一项更改,以在写入键为联合的属性时强制执行更多类型安全。仅就types而言,编译器无法区分您要执行的操作与此处绝对不安全的代码之间的区别:
function badCopy(k1: keyof ITest, k2: keyof ITest, o: ITest) {
o[k2] = o[k1]; // error!
}
在这里,keyk1
和k2
类型完全相同:keyof ITest
. 但是很有可能您正试图盲目地将一个属性从一个键复制到另一个键的不兼容属性。因为and中的键值可能不一样,尽管是相同的类型。这是不安全的,所以你会得到一个错误。k1
k2
不幸的是,即使您确定e
读取和写入中的值完全相同,该更改也会导致您正在做的事情被视为“可能不安全”。这目前被认为是 TypeScript 中的设计限制,尽管他们可能会考虑特殊大小写相同的密钥标识符。如果你关心这一点,你可能想去相关的 GitHub 问题(看起来microsoft/TypeScript#32693仍然被列为“讨论中”)并给它一个或描述你的用例,如果它比列出的更引人注目那里。
话虽这么说,但除非得到解决,否则有一些解决方法:
只要编译器看不到您使用联合类型作为键类型,编译器仍然允许将相同类型分配给自身的漏洞。通常你可以让你的函数更通用,像这样:
function copy<K extends keyof ITest>(e: K, source: ITest, dest: ITest) {
dest[e] = source[e]; // no error now
}
或者,如果您不想这样做,只需接受您比此处的编译器更了解并使用类型断言告诉它不要担心:
function copyAssert(e: keyof ITest, source: ITest, dest: ITest) {
dest[e] = source[e] as any; // one way
dest[e] = source[e] as ITest["first"] & ITest["second"]; // more explicit
}
希望其中之一对您有用。祝你好运!
推荐阅读
- angular - SharePoint Online /Angular - 错误:未捕获的错误:区域已加载
- javascript - 在 CMD(Firebase 云功能)中使用显示错误的 Rezorpay 集成
- php - 我的数据库中有图像列,它接受一个数组值,所以有什么办法可以单独更新图像
- python - 我可以找到 python 模块吗?
- apache-spark - 在 Spark 中加入两个数据框
- javascript - 在浏览器中从源捕获 Tab 音频,而不是麦克风
- apache-spark - 如何从 pyspark 数据帧中删除以 2K 开头的记录
- html - Perl & Regex:仅当字符串不在 > 和 < 之间时才替换字符串
- html - 是否可以在地址栏旁边添加文本或工具栏?
- mysql - 如何将私有 EC2 实例中的 MySQL 数据库远程连接到本地主机中的 Visual Studio