“同态映射类型”是什么意思?

2024-05-20

我在一些 TypeScript PR 中看到过“同态映射类型”这个术语。这是一个例子:https://github.com/microsoft/TypeScript/pull/21919 https://github.com/microsoft/TypeScript/pull/21919

在 --strictNullChecks 模式下,当同态映射类型删除 ?来自基础类型中的属性的修饰符它还会从该属性的类型中删除 undefined

什么是同态映射类型?同态到底是什么?有没有一个很好的例子non-同态映射类型

我感到困惑的原因是同态 https://en.wikipedia.org/wiki/Homomorphism是保留特定操作的两个结构之间的映射。这里所说的操作是什么?也就是说,在哪里f是映射,什么是op在下面的等式中:

f(x op y) = f(x) op f(y)

我尝试过的

我尝试继续假设op is &,两种类型相交的运算。

同态映射将是这样的:

F<T & U> = F<T> & F<U>

同态映射的一个例子(来自TS手册 https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types) is:

type Partial<T> = { [P in keyof T]?: T[P] }

because Partial<T & U>总是一样Partial<T> & Partial<U>.

问题是我想不出任何方法来使映射类型非同态!

即使像这样愚蠢的东西看起来也是同态的:

type Silly<T> = { [P in "foo"]: number}

让我感到困惑的是Silly似乎是同态(Silly <T & U> = Silly<T> & Silly<U>).

This seems与什么相矛盾handbook https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types表示同态映射类型:

...同态,这意味着映射仅适用于 T 的属性,而不适用于其他属性。编译器知道它可以在添加任何新的属性修饰符之前复制所有现有的属性修饰符

Silly果酱&但根据手册中的定义,它不是同态映射类型。


在 TypeScript 中,同态映射类型是编译器识别出您正在映射现有对象类型的属性的具体类型。在这种情况下,输出对象类型将具有相同的readonly和/或可选(?) 其属性上的属性修饰符与输入类型上的属性修饰符一样。我知道有几种方法可以使映射类型同态,还有一些其他方法可以使其...不。

接下来,我们使用此类型作为映射对象:

type Foo = {
    norm: string,
    opt?: string,
    readonly ro: string,
    readonly both?: string
};

主要同态映射类型技术,in keyof:

type Hom1<T> = { [P in keyof T]: number };
type Hom2<T, U> = { [K in keyof (T & U)]: K extends keyof T ? "L" : "R" };
type Hom3 = { [Q in keyof { readonly a: string, b?: number }]: Q };

在上面,您明确地迭代了keyof某物。让我们看看当我们在我们的应用程序上使用它们时您会得到什么Foo type:

type Hom1Foo = Hom1<Foo>;
/* type Hom1Foo = {
    norm: number;
    opt?: number | undefined;
    readonly ro: number;
    readonly both?: number | undefined;
}*/

type Hom2FooDate = Hom2<Foo, { z: boolean }>
/*type Hom2FooDate = {
    norm: "L";
    opt?: "L" | undefined;
    readonly ro: "L";
    readonly both?: "L" | undefined;
    z: "R";
} */

type Hom3Itself = Hom3
/* type Hom3Itself = {
    readonly a: "a";
    b?: "b" | undefined;
} */

您可以看到,在所有输出中,只读和可选标记都是从输入复制过来的。这是生成同态映射类型的主要技术,也是迄今为止最常见的技术。


二次同态映射类型技术,in K where K extends http://www.typescriptlang.org/docs/handbook/generics.html#generic-constraints keyof T是一个泛型类型参数并且T是泛型类型参数:

// <K extends keyof T, T> ... {[P in K]: ...}
type Hom4<T, K extends keyof T> = { [P in K]: 1 };

这特别使我们能够从刚刚复制属性修饰符some对象的键,并在中实现微软/TypeScript#29787 https://github.com/microsoft/TypeScript/pull/29787,主要是为了使the Pick<T, K>实用型 https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys同态。让我们看看如何Hom4行为与Foo:

type Hom4AllKeys = Hom4<Foo, keyof Foo>;
/* type Hom4AllKeys = {
    norm: 1;
    opt?: 1 | undefined;
    readonly ro: 1;
    readonly both?: 1 | undefined;
}*/

type Hom4SomeKeys = Hom4<Foo, "opt" | "ro">;
/* type Hom4SomeKeys = {
    opt?: 1 | undefined;
    readonly ro: 1;
}*/

现在几乎任何其他映射类型的使用都会给出non-同态类型。如果您不认为自己映射不同对象类型的键,那么这并不是真正的问题。例如:

type NonHom0 = { [P in "a" | "b" | "c"]: 0 };
/* type NonHom0 = {
    a: 0;
    b: 0;
    c: 0;
}*/

的属性NonHom0既不是可选的也不是只读的;为什么会这样?没有其他类型带钥匙a, b, and c从中复制它们。如果您开始想象您正在从其他对象类型复制属性,但编译器不这么认为,事情就会变得有点棘手:

type NonHom1 = { [P in "norm" | "opt" | "ro" | "both"]: Foo[P] };
/* type NonHom = {
    norm: string;
    opt: string | undefined;
    ro: string;
    both: string | undefined;
}*/

type KeysOfFoo = keyof Foo
type NonHom2 = { [K in KeysOfFoo]: 1 }
/* type NonHom2 = {
    norm: 1;
    opt: 1;
    ro: 1;
    both: 1;
} */

type NonHom3 = { [Q in Extract<keyof Foo, string>]: Foo[Q] };
/* type NonHom3 = {
    norm: string;
    opt: string | undefined;
    ro: string;
    both: string | undefined;
}*/

在这些情况下,映射是非同态的;输出类型既没有只读属性也没有可选属性。 (这| undefined仍然存在于曾经是可选的属性上,但属性本身不是可选的)。确实,您仍在迭代以下键Foo,但编译器不再认为与Foo. In NonHom1,密钥恰好相同,但没有keyof,因此编译器不会将映射识别为同态。在NonHom2,你正在使用keyof,但是编译器急切地计算KeysOfFoo这样当你到达时NonHom2,它与中的映射相同NonHom1. In NonHom3,你只是迭代string的钥匙Foo(这是全部),但是编译器再次丢失线程并且不再识别in Extract<keyof Foo, string>作为同态映射的触发器。有解决方法,请参阅 microsoft/TypeScript#24679 https://github.com/microsoft/TypeScript/issues/24679#issuecomment-394710628,但这里的重点是,如果你偏离in keyof or in K-where-K extends keyof T-和-两者-K-and-T-are-generic,你将得到非同态映射。


哇,我完成了。此后几天我都不想写“同态”这个词了。

Playground 代码链接 https://www.typescriptlang.org/play/#code/C4TwDgpgBAYg9nKBeKBvAsAKCjqA7OAJwFsAuKAZ2EIEs8BzAGi1yjjGAH5yraHnsuQhACGAEzh4ANiCiE4PanSYshoidNkAjOMAAW3SkoZYAvgG4sWAPTW0qANoBpKHSgBrCCDgAzKADpAgF1yQMDTLFBIKAAJOGIARgAeABUAPmQ0KAcABVc8Dy9fKBSQ-ABXYi0IQigLSPBoOOIAJlTGKABVDJRUbJc3T28-AAoUqAAyLoBKMpcIAA9gCDwxCkLhkqhOKAAiABldqHJdgCUj+swopviAZky+hwBFfI3ivuFxSRkoEUU+JhQLSGPCVaq1UxlF6XBrRZoJeCIFDwpKItKWTDWABUUGusXiCIQD1UOAIJHIoKqNQxrHYXApYJqUAAPlByqsID46BAxDS1F9NHIFBUqYQ+ThPhofjp9CDGbVWeyxJzubyzFjrFYro18a1EQARETLTLNNqIjp9ABe5B0cCkogKpjSNixeNNBqN0F6JPwRDIe0O4rYHEMByOio5XLwPKDku+snkJ0DPrjgplBiT4bZkdVQete3OGNMUA1WrddwAksAKBApH5kXcXbidc1blWa3XiYIJep478TiJdkHgSctFmlSro2rMMXS5gbHYkvMlis1m8-CkOukAoE0LlXk4ymEItq4fEACztKDL5ardZDYrb3rZPJuQ-kBJ1DGwm7Ec8AQSkKQnC8dYGz-VEEA6B8-DRDFsWbM8-0A4DQK7VgyX9BIgzpQxPwjZUoxjFNe0FRMoGwkiBWlXQMwolls0I3N1U1edT1-c8AGV4ggECQDA3VL3NPY6SzXZ5F2dEm3LP9uOIXi0O9btg3peiCMnYjlNTH5yMomc5y1WxfTwPR4jMwgwD0GgAGMyx1AA5SRmgABgeF9Xl2QcGN2MdvOs3Yylcy4ELxRy8Bc9DcD+KBnOHchYp9az4qLAz2KgML4Tc-c3F2TCxNE7yJO89MAvIRFciCL9pIcpz4ki0k-X+ZQcI4JqGAYiciOnVhyN4ZqfXTNr6A6nMpxS1if2vUCAHkfERTIYNgBBJoy+IWiygYCj4ihZsRMpPxPEKavCtb6t9ckKJa4AP1jYU9NYQbLrMEsJrS1biHuZ9nleABRJZCBEazgCSRbhL6hg0jKcqnkq4KcVC2qPrOzChquoaRqYsaU2FcH6GHWj0fUrrxqAA

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

“同态映射类型”是什么意思? 的相关文章

随机推荐

  • 从类似 cronjob 的语法创建“下次运行时间”日期

    在我正在创建的应用程序中 用户可以安排重复任务 生成间隔模式的简单值是 Minute 0 59 90 each minute Hour 0 23 90 each hour Day of month 1 31 90 each day of m
  • 如何使用 ProGuard 将所有方法保留在类中

    我使用 ProGuard 来优化我的 Android 应用程序 然而 对于 Android 仪器测试 我需要一些 但不是全部 类来保留所有成员 我尝试了各种方法 最后一个是 keepclassmembers public class com
  • 对客户端 JavaScript 计算器使用 eval 安全吗?

    我正在制作一个计算器 作为用户浏览器的静态 HTML 页面 该页面并非旨在将任何信息提交回服务器 除了这个计算器之外 网页上不会出现任何其他内容 在这种情况下使用 eval 安全吗 或者换句话说 在这种情况下使用 eval 是否会导致额外的
  • Qt GUI 应用程序中的控制台输出?

    我有一个在 Windows 上运行的 Qt GUI 应用程序 它允许传递命令行选项 在某些情况下我想向控制台输出一条消息 然后退出 例如 int main int argc char argv QApplication a argc arg
  • 如何从源视图 (aspx) 中的 C# 中为按钮事件添加事件处理程序

    为 HTML 源视图中的按钮创建代码隐藏 webforms 事件处理程序的最简单方法是什么 在 VB NET 中 切换到代码隐藏页面并使用顶部的对象和事件组合框来选择和创建非常容易 在 C 中 这些都缺失了 我真的不喜欢设计视图 确保 属性
  • 获取当前线程 id 和进程 id 作为整数?

    有没有办法以整数形式获取 Rust 中的当前进程 ID 和线程 ID 我得到的最接近的是 std thread current id 它返回一个不透明的ThreadId目的 当尝试访问其u64场 我得到 error E0611 field
  • SQL-Server:备份集保存现有数据库以外的数据库的备份

    我正在尝试恢复数据库的 SQL Server 备份文件 但它抛出如下错误 备份集保存除现有数据库之外的数据库的备份 我的数据库是SQL Server 2008 备份文件是2005年的 可能是什么问题 我也遇到过这个问题 解决方案 不要创建空
  • 无法解析类型为 xxx 的任何 bean;限定符:[@javax.enterprise.inject.Any()]

    我有一个 LoginProvider 接口 public interface LoginProvider boolean login String username String password 以及两种不同的实现 public clas
  • iOS UIButton 带有圆角和背景 bug

    我发现圆形 UIButton 存在一个奇怪的问题 这是我创建此按钮的代码块 let roundedButton UIButton type System roundedButton frame CGRectMake 100 100 100
  • 在 PHP 中比较两个对象的最快方法是什么?

    假设我有一个对象 在本例中为 User 对象 并且我希望能够使用单独的类来跟踪更改 用户对象不必以任何方式改变它的行为才能发生这种情况 因此 我的单独的类创建它的 干净 副本 将其存储在本地某个位置 然后可以将 User 对象与原始版本进行
  • 将 ninject 与 Ninject.Web.Api 用于 Web Api 2 一起使用在 ASP.NET MVC 5 中不起作用

    我正在开发一个 Asp NET MVC 项目 我的项目也有 web api 我正在使用 ASP NET MVC5 和 Web Api 2 以及 Visual Studio 3 我正在使用 ninject 进行依赖项注入 我知道 ninjec
  • React PropTypes 与 Flow

    PropTypes 和 Flow 涵盖相似的内容 但使用不同的方法 PropTypes 可以在运行时向您发出警告 这有助于快速找到来自服务器等的格式错误的响应 但是 Flow 似乎是未来 并且具有泛型等概念 是一个非常灵活的解决方案 Nuc
  • 在 Visual Studio Code 中调试 Go 测试

    在我的 Windows 计算机上 我安装了 Visual Studio Code 要手动运行测试 我进入控制台到项目文件夹并输入 go test main test go 它工作完美 但我遇到一种情况 我需要调试我的测试以了解发生了什么 为
  • 如何捕获一个 int

    我正在使用 IL 抛出一个 Int32 并捕获它 这只是出于好奇 我并没有试图实现任何目标 所以请不要告诉我抛出异常而不是 int method private hidebysig static void Main string args
  • div 边框上的内边距

    我想在 css 边框上添加填充 将其拉入 div 内 远离边缘 使用 css 可以吗 css3 很好 webkit 这是设计 我通过将一个 div 放在一个 div 中 然后给内部 div 一个边框来做到这一点 我想让标记尽可能精简 所以如
  • 为什么main()后面有函数定义?

    我假设最常用的系统功能之一 ls由最权威的程序员之一 Richard Stallman 编写的最著名的操作系统之一 linux 的代码可能是真正编写良好的代码的一个例子 因此 由于它是开源的 我决定看一下代码 参见例如here http m
  • Netty通道读取混乱

    我三个月前开始使用 Netty 最初 它看起来非常简单且易于使用 因为我遵循了 4 x 系列主页中给出的示例 当我更深入地探索它时 我无法理解某些事件或回调名称 例如 我无法理解以下内容之间的区别 ChannelRead ChannelHa
  • Swift 3.0 Pin 颜色注释在 MapView 中没有改变

    我有兴趣根据案例场景更改注释的图钉颜色 在一个函数中 我发送了一个数组 用于确定引脚注释的颜色 到目前为止 我已经设置了一个名为 ColorPointAnnotation 的子类 它将确定 pinColor 然后 在 switch 语句中
  • 如何在 Loopback 4 中使用有状态请求?

    在 v3 中 我们可以在底层 Express 上定义中间件 例如快速会话 https github com expressjs session 添加一个session请求对象上的属性 在 v4 中 看起来没有对应的东西 并且底层的 Expr
  • “同态映射类型”是什么意思?

    我在一些 TypeScript PR 中看到过 同态映射类型 这个术语 这是一个例子 https github com microsoft TypeScript pull 21919 https github com microsoft T