否定打字稿类型?

2024-02-20

我想在打字稿中创建一个简单的 NOT 运算符,您可以将所有基元组合到某种类型 A 的联合中,这些基元不是第二种类型 B 的联合的基元成员。这可以使用条件类型来完成。例如,如果您有类型:

type A = 'a' | 'b' | 'c';
type B = 'c' | 'd' | 'e'; 

...然后我想将它们映射到第三个派生类型 [A - B],在这种情况下,将产生:

type C = 'a' | 'b'

使用如下所示形式的条件似乎可以实现这一点。然而,我完全困惑为什么下面的 NOT 运算符似乎给了我我想要的东西,但明确地拼写出完全相同的条件逻辑却没有:

type not_A_B_1 = A extends B ? never : A;   // 'a' | 'b' | 'c'

type Not<T, U> = T extends U ? never : T;   
type not_A_B_2 = Not<A, B>                  // 'a' | 'b'

See here https://www.typescriptlang.org/play/#src=%0D%0Atype%20A%20%3D%20'a'%20%7C%20'b'%20%7C%20'c'%3B%0D%0Atype%20B%20%3D%20'c'%20%7C%20'd'%20%7C%20'e'%3B%20%0D%0A%0D%0A%0D%0Atype%20not_A_B_1%20%3D%20A%20extends%20B%20%3F%20never%20%3A%20A%3B%20%20%20%2F%2F%20'a'%20%7C%20'b'%20%7C%20'c'%0D%0A%0D%0Atype%20Not%3CT%2C%20U%3E%20%3D%20T%20extends%20U%20%3F%20never%20%3A%20T%3B%20%20%20%0D%0Atype%20not_A_B_2%20%3D%20Not%3CA%2C%20B%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20'a'%20%7C%20'b'%0D%0A%0D%0A.

有人可以告诉我我是否在这里遗漏了一些 TS 的微妙之处来解释为什么not_A_B_1 and not_A_B_2不等价吗?谢谢。


你遇到过分配条件类型 https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#distributive-conditional-types:

所检查的类型是裸类型参数的条件类型被称为分配条件类型。分布式条件类型在实例化期间自动分布在联合类型上。例如,一个实例化T extends U ? X : Y使用类型参数A | B | C for T被解析为(A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)

所以在此:

type not_A_B_1 = A extends B ? never : A;   // 'a' | 'b' | 'c'

The A是具体类型,而不是类型参数,因此条件类型does not分配给其选民。

But in

type Not<T, U> = T extends U ? never : T;   

the T是一个裸类型参数,所以条件类型does得到分发。 “裸体”是什么意思?它的意思是T与某些类型的函数相反T。所以在{foo: T} extends W ? X : Y, 类型参数T是“穿衣”的,所以它不会分发。

这导致了一种在您不需要分配条件类型时关闭它们的方法:装饰类型参数。最简单且最不冗长的方法是使用tuple https://www.typescriptlang.org/docs/handbook/basic-types.html#tuple一个元素的:所以,

T extends U ? V : W // naked T
[T] extends [U] ? V : W // clothed T

Since [T] extends [U]准确的时间应该是正确的T extends U,除了分布性之外,它们是等价的。所以让我们改变一下Not<>非分配性:

type NotNoDistribute<T, U> = [T] extends [U] ? never : T;   
type not_A_B_2 = NotNoDistribute<A, B>                  // 'a' | 'b' | 'c'

Now not_A_B_2是相同的not_A_B_1。如果你更喜欢原版not_A_B_2行为,然后使用分布式条件类型,例如Not<>。如果您更喜欢非分配行为,请使用具体类型或固定类型参数。那有意义吗?

顺便说一下,你的Not<T,U>类型已经作为预定义类型 https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#predefined-conditional-types在标准库中为Exclude<T,U> https://github.com/Microsoft/TypeScript/blob/v3.0.1/lib/lib.es5.d.ts#L1386-L1389,意思是“排除T那些可分配给的类型U".

希望有帮助。祝你好运!

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

否定打字稿类型? 的相关文章

随机推荐

  • 如何在Android中使用默认动画?

    我正在尝试使用带有片段的活动的默认动画 在这里我发现了一些关于它的信息 Android 对Fragment使用Activity的默认动画 https stackoverflow com questions 14376810 android
  • Mavericks 上的 MySQL 服务器启动问题

    我在 MacBook 上使用 MySQL 时遇到困难 我正在尝试使用以下命令启动我的服务器sudo mysqld safe这会产生以下输出 140131 00 03 02 mysqld safe Logging to usr local v
  • 不使用 eval/new 函数的 JavaScript 模板库

    Google Chrome 扩展程序使用manifest version 2被限制使用eval or new Function 我检查的所有 JavaScript 模板库 mustachejs underscorejs jQuery 模板
  • Laravel 覆盖命名路线并采取错误的路线

    我在我的routes php 文件中定义了这个 Route post gestionAdministrador array as gt Loguearse uses gt AdministradorController Login Rout
  • 谷歌应用引擎上的 psycopg2 出现问题

    当我尝试在我的谷歌应用程序引擎应用程序中实现框架 Pony ORM 时遇到问题 关键是 Pony 使用 psycopg2 PostgreSQL 适配器 当我尝试向数据库发出请求时 它会引发一个异常 它找不到 psycopg2 模块 在本地
  • data-sly-use、data-sly-resource、data-sly-include 和 data-sly-template 之间有什么区别?

    有什么区别 data sly use data sly resource data sly include and data sly template 我正在阅读文档Sightly AEM我非常困惑 据我所知 data sly use用于添
  • 为 STL 随机数生成器编写工厂方法

    我正在尝试通过配置文件提供一个界面 以便我的用户为他们正在使用的某些参数选择一个发行版 我想使用 STL 随机数生成器算法来实现此目的 假设我的程序从命令行读取 JSON 对于下面提供的 JSON 程序需要意识到它应该根据给定均值和标准差的
  • C# 是否有一个好的 leveldb 端口? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我希望在我的纯 C 项目中使用 leveldb 我在 google 上搜索了 leveldb 的 C 版本 但没有找到 谁能告诉我在哪里可
  • JAXB 按原样使用 String

    我使用 REST 我想知道是否可以告诉 jaxb 将字符串字段 按原样 插入到传出的 xml 中 当然 我想在返回之前将其拆开 但我想节省这一步 XmlRootElement name unnestedResponse public cla
  • 在 Three.js 继承模式中对原型使用扩展有什么好处?

    使用优秀的 Three js 框架 目前正在寻找良好的 javascript 继承模式 我了解了 Three js 中所做的事情 我现在对正在发生的事情有了很好的了解 除了一些 类 例如 Vector3 特别是 我不清楚为什么有些方法是直接
  • 如何在 svelte 中访问 websocket?

    我正在尝试将 svelte 连接到 fastapi 后端 但使用 svelte 套件时出现此错误 我明白了 WebSocket is not defined ReferenceError WebSocket is not defined e
  • cherrypy.HTTPRedirect 使用绝对路径重定向到 IP 而不是主机名

    我在 nginx 后面运行 CherryPy 并需要处理重定向 在我的在 127 0 0 1 8080 上运行的开发机器上 这会正确重定向到 127 0 0 1 8080 login 然而 当通过 nginx 在cherrypy mydom
  • 将数据块读入matlab数组

    我有一个如下所示的数据文件 3 1 0 1 4 1 7 2 1 2 1 5 1 1 1 2 1 1 1 2 对于每一行 第一个整数表示该行中浮点数的数量 现在我想将所有数据加载到一个matlab数组中 并忽略第一列 也就是说 我想得到一个像
  • 原则:多个(whereIn OR whereIn)查询?

    我在用 Doctrine 编写一个相当简单的查询时遇到了麻烦 我有两个数组 countries cities 我需要检查数据库记录值是否与其中的任何一个匹配 我正在寻找类似的东西 gt whereIn country city countr
  • 当文件在其他进程中使用时删除该文件

    In DocumentViewerControl在 WPF 中 我想在关闭事件处理程序中关闭控件后删除该文件 我试图删除它 但 VS 告诉我它被另一个进程使用 我怎样才能删除它 TextBlock tb TextBlock e TabIte
  • Akka设计原则

    在开发一个相当大的 Akka 应用程序时 我在使用普通方法和非 Akka 类时遇到了一个非常简单的结构 但在使用 Akka 时实际上很难确定 这就是为什么我来这里问你什么建议是解决此问题的最佳方法 所以问题是这样的 我有一个父角色 我们称他
  • 在没有 Adob​​e Reader 的情况下将 pdf 文件显示到浏览器中

    我需要在没有 Adob e Reader 的情况下在浏览器中打开 pdf 文件 是否有 PHP 的 API 可以在浏览器中打开 PDF 文件 Regards No PHP 在服务器上运行 它可以访问的唯一 浏览器 API 是 HTTP 如果
  • 如何在非 root 运行的容器中安装新包?

    我需要在正在运行的容器中安装简单的包 例如curl 但我遇到了这个错误 apk add curl ERROR Unable to lock database Permission denied ERROR Failed to open ap
  • 将 System.out 和 System.err 重定向到 slf4j

    我需要重定向System out err println输出到 slf4j 我知道这不是正确进行日志记录的方法但有一个外部库 它记录到System out 您可以使用slf4j 上的系统输出 http projects lidalia or
  • 否定打字稿类型?

    我想在打字稿中创建一个简单的 NOT 运算符 您可以将所有基元组合到某种类型 A 的联合中 这些基元不是第二种类型 B 的联合的基元成员 这可以使用条件类型来完成 例如 如果您有类型 type A a b c type B c d e 然后