typescript - 在这种情况下,TypeScript 类型系统是否过于宽松?
问题描述
我想我遇到了一个似乎应该导致 TS 编译器出错的场景(但事实并非如此),我希望有人能解释原因。
在下面的代码中,我将一个接口传递给它接受Foo
的函数。frobnicator
然后,在 的正文中frobnicator
,我“删除”了该字段bar.y
。终止后frobnicator
,类型系统允许我打印bar.y
(没有错误),尽管y
不再存在。
类型系统不应该禁止我传递foo
到,frobnicator
因为现在foo
不再实现Foo
接口并且 TS 认为它实现了吗?
interface Foo {
bar: { x: number, y: number };
}
function frobnicator(thing: { bar: { x: number } }) {
thing.bar = { x: 1 }; // "remove" bar.y
}
const foo: Foo = { bar: { x: 1, y: 2 } };
frobnicator(foo); // The implementation "removes" bar.y
console.log(foo.bar.y); // TypeScript does not error despite bar.y missing
解决方案
您的界面与函数内的代码无关,因为即使您的 const 的类型是 Foo,该函数接受的不是 foo,而是未命名的类型{ bar: { x: number } }
。由于 Typescript 在编译时而不是在运行时工作,它不可能知道您的函数已被删除y
,因为函数内部的类型没有y
,而它外部Foo
的类型是函数参数类型的超类型,因此它的实例适合参数的类型。所以,一方面你的函数从对象中删除了一个字段,但你没有告诉编译器它是被禁止的,因为函数内部的类型与你传入的类型不同,所以外部它仍然认为你有y
. 在像 Java 这样的语言之后,这似乎违反直觉,但事实就是如此。为避免此类问题,您应该使用正确的类型,例如,在函数中使用您的接口类型。
推荐阅读
- php - 错误的请求。无法解码响应:解析服务器
- azure - 在 azure logic App 中如何将 Cookie 传递给 Http 请求
- javascript - 将元素与 Bootstrap 过滤器保持在一起
- python - 在python中读取和重写PDF文件使其无法打开
- c++ - 如何准备 msgpack 通过 ZeroMQ 基础设施发送结构?
- jquery - 调整视口宽度的引导工具提示数据放置
- c - 如何使循环输出中的字符居中?
- multithreading - 使用 HttpContextBase 设置 HttpContext.Current
- python - QCompleter 从多列中选择数据
- python - 隐藏 xticks 标签每个第 n 个标签或 Pandas 图上的值/使 x 轴可读