如何确保元组元素标签被保留?

2024-02-28

背景

我正在尝试使用带标签的元组元素将现有的重载函数替换为剩余参数。

原始代码

这是原始重载函数的简化版本:

function doSomething(arg1: string, arg2: number):void;
function doSomething(arg1: string, arg2: number, arg3: unknown[]):void;
function doSomething(arg1: string, arg2: number, arg3: boolean):void;
function doSomething(arg1: string, arg2: number, arg3: unknown[], arg4: boolean):void {
    // ...implementation
}

因此第三个和第四个参数是可选的,但提供时顺序可以是:

arg3: unknown[]
arg3: unknown[], arg4: boolean
arg3: boolean

尝试的解决方案

我决定首先创建带标签的元组元素,然后根据提供的类型变量类型将其类型设置为提供的类型或never。然后过滤该元组,删除任何元素never并返回结果。

type CalcAdditionArgs<ThirdArgType extends unknown[], FourthArgType extends boolean> = [
    myArg3: ThirdArgType extends [] ? never : ThirdArgType,
    myArg4 : [FourthArgType] extends [boolean] ? FourthArgType extends true ? true : never : never
]

type GetAdditionalArgs<ThirdArgType extends unknown[], FourthArgType extends boolean> = 
    FilterType<CalcAdditionArgs<ThirdArgType, FourthArgType>,  never>

FilterType是此处找到的元组过滤实用程序的修改版本https://stackoverflow.com/a/64034671/1798234 https://stackoverflow.com/a/64034671/1798234

type FilterType<T extends unknown[], U = undefined> = 
    (T extends [] ? 
        [] :
        (T extends [infer H, ...infer R] ?
            ([H] extends [U] ?
                FilterType<R, U> :
                [H, ...FilterType<R, U>]) : 
            T
        )
    );

为了清楚起见,这是使用它们的函数

function execute<
    ThirdArgType extends unknown[] = [],
    FourthArgType extends boolean = false
>(
    arg1: string,
    arg2: number,
    ...args:GetAdditionalArgs<ThirdArgType, FourthArgType>
    
): void {
    // do something here
}

Problem

这是两种实用程序类型的输出:

type a = CalcAdditionArgs<[], false>; //  [myArg3: never, myArg4: never]
type b = CalcAdditionArgs<[], true>; // [myArg3: [string, number], myArg4: never]
type c = CalcAdditionArgs<[string, number], false>; // [myArg3: [string, number], myArg4: never]
type d = CalcAdditionArgs<[string, number, Function], true>; // [myArg3: [string, number, Function], myArg4: true]

type e = GetAdditionalArgs<[], false>; // []
type f = GetAdditionalArgs<[], true>; // [true]
type g = GetAdditionalArgs<[string, number], false>; // [string: number]
type h = GetAdditionalArgs<[string, number, Function], true>; // [[string, number, Function], true]

如你看到的,GetAdditionalArgs(更确切地说FilterType) 正在剥离元组元素标签。

Question

我无法理解如何(如果实际上可能)在实用程序类型中创建然后操作元组类型。即创建一个空元组,然后向其中添加所需的类型。因此,我的解决方案方法是预先创建填充的元组,然后删除元素。

  1. 有谁知道为什么元组元素标签被剥离FilterType有没有办法使用现有的解决方案来解决这个问题?

Or

  1. 有没有更好/更简单的解决方案来实现我正在寻找的结果?

Solution

感谢@captain-yossarian 的回复以及@ford04 的回复(https://stackoverflow.com/a/64194372/1798234 https://stackoverflow.com/a/64194372/1798234)我能够使用剩余参数重新思考我的解决方案方法:

type Append<E extends [unknown], A extends unknown[]> = [...A, ...E]

type GetMyArrayArg<T extends unknown[]> = [myArrayArg: T extends [] ? never : T]
type GetMyBooleanArg<T extends boolean> = [myBooleanArg : [T] extends [boolean] ? T extends true ? true : never : never]


type AddParameter<T extends [unknown], U extends unknown[] = []> =
    T extends [] ? 
        U :
        T extends [infer H] ?
            [H] extends [never] ? 
                U : 
                Append<T, U> :
            U

type GetAdditionalArgs<ThirdArgType extends unknown[], FourthArgType extends boolean> = 
    AddParameter<
        GetMyBooleanArg<FourthArgType>, 
        AddParameter<
            GetMyArrayArg<ThirdArgType>>
        >


type a = GetAdditionalArgs<[], false>; // []
type b = GetAdditionalArgs<[], true>; // [myBooleanArg: true]
type c = GetAdditionalArgs<[string, number], false>; // [myArrayArg: [string, number]]
type d = GetAdditionalArgs<[string, number, Function], true>; // [myArrayArg: [string, number, Function], myBooleanArg: true]

如果您好奇为什么从输出中删除元组标签,可能很难回答。

首先,在这里你可以找到docs https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html#labeled-tuple-elements .

根据文档:

它们纯粹用于文档和工具

这只是我的猜测。

我认为标签被删除是因为FilterType实用类型。FilterType创建全新的元组,并且 TS 似乎在迭代期间不保留元组标签。

考虑这个例子:

type Labeled = [name: string];

type Infer<L extends Labeled> = L extends [infer First] ? [First] : never

type Result = Infer<Labeled> // [string], no label

数字索引也不保留标签。[L[0]]- 退货[string].

似乎它与其余参数一起使用:

type Labeled = [name: string];

type Infer<L extends Labeled> = L extends [infer _] ? [...L] : never

type Result = Infer<Labeled> // [name: string], with label

CalcAdditionArgs不创建新元组。

我在文档中没有找到如何保留标签。

我假设,既然您在中创建了新元组FilterType,元素的顺序可能不会保留。因此,保留标签可能不安全。但这只是我的猜测。

Here https://github.com/microsoft/TypeScript/pull/38234你可以找到公关


但是,您可以将标签添加到FilterType:

type FilterType<T extends unknown[], U = undefined> =
    (T extends [] ?
        [] :
        (T extends [infer H, ...infer R] ?
            ([H] extends [U] ?
                FilterType<R, U> :
                [Batman: H, ...Superman: FilterType<R, U>]) : // <----- LABELS
            T
        )
    );

正如您可能已经注意到的,我添加了Batman标签和Superman标签,它们存在于输出中:

type FilterType<T extends unknown[], U = undefined> =
    (T extends [] ?
        [] :
        (T extends [infer H, ...infer R] ?
            ([H] extends [U] ?
                FilterType<R, U> :
                [Batman: H, ...Superman: FilterType<R, U>]) :
            T
        )
    );


type CalcAdditionArgs<ThirdArgType extends unknown[], FourthArgType extends boolean> = [
    myArg3: ThirdArgType extends [] ? never : ThirdArgType,
    myArg4: [FourthArgType] extends [boolean] ? FourthArgType extends true ? true : never : never
]

type GetAdditionalArgs<ThirdArgType extends unknown[], FourthArgType extends boolean> =
    FilterType<CalcAdditionArgs<ThirdArgType, FourthArgType>, never>


type e = GetAdditionalArgs<[], false>; // []
type f = GetAdditionalArgs<[], true>; // [Batman: true]
type g = GetAdditionalArgs<[string, number], false>; // [Batman: [string, number]]
type h = GetAdditionalArgs<[string, number, Function], true>; // [Batman: [string, number, Function], Batman: true]

如果这不符合您的期望,您可以手动创建允许的元组的并集。这将是最安全的方式

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

如何确保元组元素标签被保留? 的相关文章

随机推荐

  • Rails 中 Factory Girl 的单表继承

    我正在做一个Rails 4 0 1应用程序使用Capybara and FactoryGirl但我无法让我的测试正常工作 我正在使用单表继承来制作Collection lt ActiveRecord Base and a VideoColl
  • 如何使用 Autofixture 创建和填充我的模拟类?

    目前 我正在使用 EF6 在 UnitOfWork 内实现我的存储库 我还创建了一个内存中模拟实现 MockUnitOfWork 和 MockRepository 以便我可以在单元测试中使用它们 但是我现在必须处理对象的繁琐设置 这不就是
  • CFBuilder 没有在断点处停止

    既然这个问题 Eclipse 不会在断点处停止 https stackoverflow com questions 4388192 eclipse doesnt stop at breakpoints 处理 eclipse 本身 CFBui
  • rpm-maven-plugin 参数“sourceEncoding”丢失或无效

    我正在尝试使用 rpm maven 插件 但出现以下错误 错误 无法在项目 TestRpmAndDocker 上执行目标 org codehaus mojo rpm maven plugin 2 1 3 rpm generate rpm 目
  • 使用带有索引位置的 addChild

    当我添加子节点时 如何根据它的兄弟节点选择它的位置 这是一个例子
  • 在 Python 中将 float.hex() 值转换为二进制

    我想知道如何转换返回的结果float hex 到二进制 例如 从0x1 a000000000000p 2 to 110 1 有人可以帮忙吗 谢谢 def float to binary num exponent 0 shifted num
  • 如何在 dart 中等待 Map.forEach()

    我有一个返回地图的 Future 然后 我需要使用该映射的值来等待另一个未来 然后在最后返回整个结果 问题是 dart 不能等待async Map forEach 方法 参见 https stackoverflow com a 424678
  • 将 postgres 函数与查询结合起来

    我目前正在努力处理结果集中需要的 sql 函数的输出 SELECT getAdditionalInfoAboutDate date from sampleCalendar 问题是 我通过以下方式得到结果 属性1 属性2 属性3 属性2 属性
  • 如何使用toggle()在jquery中设置cookie

    当用户单击链接时 寻找要设置的 cookie 它将打开 div 然后用户可以刷新页面并看到 div 仍然打开 HTML a class show settings href a jQuery function Toggle Settings
  • Oracle 中的标识符太长

    我正在尝试在 SQL Developer 中创建表 但收到此错误 错误 SQL ORA 00972 标识符太长 CREATE TABLE PACIENTE IdentificacionID number 5 TipoIdentificaci
  • 在 ASP.Net Core MVC 中使用 AJAX 提交表单

    我正在使用 ASP Net Core 2 1 并尝试在返回文件的 url 时上传文件 而不刷新页面 我正在尝试在 site js 中编写 JavaScript 因为 RenderPartial scripts 在页面末尾呈现所有脚本 因此在
  • Cassandra CQL 通配符搜索

    我有一个像这样的表结构 创建表文件 id 文本主键 fname 文本 mimetype 文本 isdir 布尔值 位置文本 在文件 位置 上创建索引 file location 表中内容如下 插入文件 id fname mimetype i
  • 将 Reactjs 连接到 Myqtthub

    您好 我对所有物联网事物都很陌生 我希望能够使用 mqtt 从 Arduino 发送和接收数据https myqtthub com https myqtthub com作为我们的经纪人 我使用以下代码进行连接 import React Co
  • 傅里叶变换+emgucv

    谁能告诉我这段代码有什么问题吗 基本上我正在尝试计算图像的 dft 并将其显示为屏幕上的图像 Image
  • 发布的歌曲 URL 是否是 Facebook 的嵌入式音乐播放器?

    我们希望我们的会员能够分享我们网站上的歌曲 并能够在 Facebook 帖子中收听这些歌曲 SoundCloud 能够做到这一点 如他们在他们的页面在这里 https www facebook com soundcloud 他们是通过成为白
  • MATLAB 中的字符串索引:单引号与双引号

    我有一个字符串矩阵 如下所示 readFiles 11221 09 11222 13 12821 06 13521 02 13522 13 13711 05 13921 01 14521 001 15712 003 它们用于以自动方式访问某
  • CUDA 使用解释器还是编译器?

    这是一个有点愚蠢的问题 但我想知道 CUDA 使用解释器还是编译器 我很想知道 因为我不太确定 CUDA 如何设法让源代码在具有不同计算能力的两张卡上运行 来自维基百科 http en wikipedia org wiki CUDA 程序员
  • 如何使用 serde_json 将“NaN”反序列化为“nan”?

    我的数据类型如下所示 derive Serialize Deserialize Debug serde rename all camelCase pub struct Matrix serde rename numColumns pub n
  • Firebase 函数返回“响应不是有效的 JSON 对象。”

    我正在尝试从以下地址发送电子邮件firebase我从我的函数调用vue应用程序 我的 firebase 函数如下所示 const functions require firebase functions const admin requir
  • 如何确保元组元素标签被保留?

    背景 我正在尝试使用带标签的元组元素将现有的重载函数替换为剩余参数 原始代码 这是原始重载函数的简化版本 function doSomething arg1 string arg2 number void function doSometh