打字稿交集类型和函数签名不会引发预期错误

2024-05-13

我声明了以下类型:

type ExampleA = {
    a: string;
}

type ExampleB = {
    b: number;
}

type ExampleC = {
    c: boolean;
}

type Examples = ExampleA &
    ExampleB &
    ExampleC;

然后我使用如下类型:

function foo(pattern: { [key: string]: string }) {
    console.log(pattern);
}

const bar: Examples = { a: 'foo', b: 1, c: false }; 
foo(bar);

打字稿编译器在调用时不会抛出任何错误foo(bar)方法,尽管bar:Examples变量与函数签名不匹配foo.

游乐场链接 http://www.typescriptlang.org/play/index.html#src=type%20ExampleA%20=%20%7B%0A%20%20a:%20string;%0A%7D%0A%0Atype%20ExampleB%20=%20%7B%0A%20%20b:%20number;%0A%7D%0A%0Atype%20ExampleC%20=%20%7B%0A%20%20c:%20boolean;%0A%7D%0A%0Atype%20Examples%20=%20ExampleA%20&%0A%20%20ExampleB%20&%0A%20%20ExampleC;%0A%0A%0Afunction%20foo(pattern:%20%7B%20%5Bkey:%20string%5D:%20string%20%7D)%20%7B%0A%20%20console.log(pattern);%0A%7D%0A%0Aconst%20bar:%20Examples%20=%20%7B%20a:%20'foo',%20b:%201,%20c:%20false%20%7D;%20%0Afoo(bar);//%20there%20should%20be%20an%20Error%20here%0A%20%20%20%20%20%20%20%20%20//%20since%20ExampleB%20and%20ExampleC%20don't%20match%20the%20method%20signature%0A%0A

为什么打字稿没有抛出任何错误?这是编译器中的错误吗?


其工作原理是交集类型与其基本类型的可分配性。

作为交叉口类型,Examples可分配给ExampleA. ExampleA可分配给{ [key: string]: string }。所以,Examples必须可分配给函数参数类型

这可以在这段代码中显示:

const bar: Examples = { a: 'foo', b: 1, c: false }; 
const bar2: ExampleA = bar;
const bar3: { [key: string]: string } = bar2;
foo(bar3); //This works
foo(bar2); //Since the assignment bar3 = bar2 works, this must work, too
foo(bar); //Since the assignment bar2 = bar works, this must work, too

游乐场版 http://www.typescriptlang.org/play/index.html#src=type%20ExampleA%20%3D%20%7B%0A%20%20a%3A%20string%3B%0A%7D%0A%0Atype%20ExampleB%20%3D%20%7B%0A%20%20b%3A%20number%3B%0A%7D%0A%0Atype%20ExampleC%20%3D%20%7B%0A%20%20c%3A%20boolean%3B%0A%7D%0A%0Atype%20Examples%20%3D%20ExampleA%20%26%0A%20%20ExampleB%20%26%0A%20%20ExampleC%3B%0A%0A%0Afunction%20foo(pattern%3A%20%7B%20%5Bkey%3A%20string%5D%3A%20string%20%7D)%20%7B%0A%20%20console.log(pattern)%3B%0A%7D%0A%0Aconst%20bar%3A%20Examples%20%3D%20%7B%20a%3A%20'foo'%2C%20b%3A%201%2C%20c%3A%20false%20%7D%3B%20%0Aconst%20bar2%3A%20ExampleA%20%3D%20bar%3B%0Aconst%20bar3%3A%20%7B%20%5Bkey%3A%20string%5D%3A%20string%20%7D%20%3D%20bar2%3B%0Afoo(bar3)%3B%20%2F%2FThis%20works%0Afoo(bar2)%3B%20%2F%2FSince%20the%20assignment%20bar3%20%3D%20bar2%20works%2C%20this%20must%20work%2C%20too%0Afoo(bar)%3B%20%2F%2FSince%20the%20assignment%20bar2%20%3D%20bar%20works%2C%20this%20must%20work%2C%20too%0A%0A


UPDATE

当您想要坚持“当 A 可分配给 B 并且 B 可分配给 C 时,则 Amust可分配给 C"。类型系统除了允许此类分配之外别无选择。然而,实际上有is将值作为参数传递给的另一个问题foo.

您可以将值分配给仅共享所分配值的部分成员的类型的变量。所以这个作业工作得很好:

let item: { a: string, b: number } = { a: "Hello World!", b: 1 };
let partiallyMatchingItem: { a: string } = item;

绝对没问题partiallyMatchingItem具有比类型中实际声明的属性更多的属性。保证是最低保证。

然而,对映射类型的分配不起作用,因为item类型的附加成员number:

let item = { a: "Hello World!", b: 1 };
let mappedTypeItem: { [key: string]: string } = item; //Error

所以这次的保证是not是最低限度的保证,更是绝对的保证。当你考虑到你可以多么容易地绕过它(有意或无意)时,这是相当荒谬的:

let item = { a: "Hello World!", b: 1 };
let partiallyMatchingItem: { a: string } = item;
let mappedTypeItem: { [key: string]: string } = partiallyMatchingItem;

或者简单地:

let item = { a: "Hello World!", b: 1 };
let mappedTypeItem: { [key: string]: string } = item as { a: string };

这是一个等待发生的错误,特别是当您枚举以下属性时mappedTypeItem并且您假设所有属性的值都是string.

考虑到结构类型赋值在 TypeScript 中非常常见,这种绝对保证不适合类型系统通常提供的最低保证系统。

一个干净的解决方案是创建“常规”类型的值not可分配给映射类型(如果需要向后兼容性,您可以使用tsconfig.json文件)。至少您应该避免此类分配,因为此处提供的类型安全性非常弱。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

打字稿交集类型和函数签名不会引发预期错误 的相关文章

随机推荐

  • 如何在 Ruby 中列出局部变量?

    def method a 3 b 4 some method that gives a b end 局部变量 http ruby doc org core Kernel html method i local variables 它输出符号
  • 在 TinyMCE 中插入换行符而不是

    我已按如下方式初始化 TinyMCE 我想在用户按 Enter 键而不是段落时强制换行 我正在尝试关注 但没有成功 我正在使用 TinyMCE 版本 3 3 8 tinyMCE init mode exact theme advanced
  • Travis CI 与 Clang 3.4 和 C++11

    Travis CI 是否可以与支持 C 11 的 Clang 一起使用 我想要 Clang 而不是 GCC 我已经在 Travis CI 中使用了 GCC 4 8 看来预安装的版本不支持 C 11 我安装任何新版本的所有尝试都结束了因为这个
  • Express.js - 监听关闭

    我有一个使用 Express 的 Node js 应用程序 在该应用程序中 我有一个如下所示的块 const app require app const port process env PORT 8080 const server app
  • T-SQL 按最旧日期和唯一类别选择行

    我正在使用 Microsoft SQL 我有一个表 其中包含按两个不同类别存储的信息和一个日期 例如 ID Cat1 Cat2 Date Time Data 1 1 A 11 00 456 2 1 B 11 01 789 3 1 A 11
  • 如何在 Visual Studio Code 中缩进/格式化所选代码?

    我想缩进 Visual Studio Code 中的特定代码部分 I read 如何在 Visual Studio Code 中设置代码格式 https stackoverflow com questions 29973357 它提供了缩进
  • 根据两个预先计算的直方图报告两个样本的 K-S 统计量

    Problem 在这里 我绘制了存储在文本文件中的 2 个数据集 在列表中 dataset 每个包含 218 亿个数据点 这使得数据太大而无法作为数组保存在内存中 我仍然能够将它们绘制为直方图 但我不确定如何通过2 样本KS测试 http
  • 如何使用 PHP 中的 jQuery/AJAX 调用迭代 JSON 数组? [复制]

    这个问题在这里已经有答案了 可能的重复 循环Json对象 https stackoverflow com questions 684672 loop through json object 我有一个 PHP 函数 data php 它从外部
  • 使用 AesManaged“填充无效且无法删除”

    我正在尝试使用 AesManaged 进行简单的加密 解密 但在尝试关闭解密流时不断出现异常 这里的字符串被正确加密和解 密 然后在 Console WriteLine 打印正确的字符串后 我收到 CryptographicExceptio
  • 在 Fedora 上安装 SDL

    我安装了 FEDORA 和 SDL 并希望在编译时用 C 语言对图形进行编程 我收到了很多对 SDL MapRGB SDL Init 等未定义的引用 我搜索了文件系统 SDL dll 丢失 如何解决这个问题呢 Linux不使用 dll文件来
  • 拆分具有多行文本和单行文本的行

    我试图弄清楚如何拆分数据行 其中行中的 B C D 列包含多行 而其他列不包含多行 我已经弄清楚如何拆分多行单元格 如果我将这些列复制到新工作表中 手动插入行 然后运行下面的宏 仅适用于 A 列 但我在编码时迷失了休息 Here s wha
  • Bootstrap shown.bs.tab 事件不起作用

    我正在使用灵活的模板 http the8guild com themes html flexy v1 7 stylesPage html 使用引导程序 并且我无法让选项卡上的 shown bs tab 事件正常工作 我已经成功让它发挥作用J
  • OSX Swift 在默认浏览器中打开 URL

    如何使用 Swift 作为编程语言和 OSX 作为平台在系统默认浏览器中打开 URL 我发现了很多UIApplication like UIApplication sharedApplication openURL NSURL string
  • 可拖动的非模态弹出窗口 Jquery Mobile

    我希望在 Jquery mobile 中有一个弹出窗口 它不会阻止用户与页面交互 并且 data dismissible false 即当页面的另一部分与页面的另一部分交互并保持可见时 弹出窗口不会消失 我已经尝试过这个 popupNew
  • 从本地计算机连接到 AWS 上的 Neptune

    我正在尝试从办公室的本地计算机连接到 AWS 实例中的 Neptune DB 就像从办公室连接到 RDS 一样 是否可以从本地计算机连接 Neptune 数据库 Neptune 数据库是否公开可用 开发人员有什么方法可以从办公室连接 Nep
  • 使用 SSL 和代理设置的 Rest 客户端获取连接超时

    我正在使用带有忽略 ssl 的 Rest 客户端 它工作正常 但在将来我尝试使用客户端证书进行的生产中将无法工作 我有 ca 证书和客户端证书 我用它创建了一个客户端 但我收到错误 Exception in thread main com
  • ASP.Net:动态添加到占位符的用户控件无法检索值

    我将一些用户控件动态添加到 PlaceHolder 服务器控件中 我的用户控件由一些标签和一些文本框控件组成 当我提交表单并尝试查看服务器上文本框 在每个用户控件内 的内容时 它们是空的 回发完成后 文本框将包含我在回发之前输入的数据 这告
  • AES 会话密钥的 RSA 解密失败,并显示“AttributeError:‘bytes’对象没有属性‘n’”

    我正在努力在 Python 3 6 上从 PyCryptodome 实现公钥加密 当我尝试创建对称加密密钥并加密 解密变量时 一切正常 但是当我引入 RSA 和 PKCS1 OAEP 的那一刻 一切就都顺理成章了 session key加密
  • CMake Xcode生成器创建了一个无法构建的项目

    我有一个使用 CMake 构建系统的 C 项目 我使用 MacBook Pro 进行开发 因此当我使用终端时 一切都非常顺利 我可以构建我的项目 然而 今天我发现我可以在使用 CMake 生成器创建相应的项目后使用 Xcode gt cma
  • 打字稿交集类型和函数签名不会引发预期错误

    我声明了以下类型 type ExampleA a string type ExampleB b number type ExampleC c boolean type Examples ExampleA ExampleB ExampleC