【问题标题】:Push type to the end of the tuple将类型推送到元组的末尾
【发布时间】:2020-02-21 02:37:09
【问题描述】:

我可以在元组的开头添加元素,或者从那里删除它

type ShiftTuple<T extends any[]> = ((...t: T) => void) extends ((x: infer X, ...r: infer R) => void) ? R : never;
type UnshiftTuple<X, T extends any[]> = ((x: X, ...t: T) => void) extends ((...r: infer R) => void) ? R : never;

但是我很难用最后一个元素而不是第一个元素做同样的事情。

即使我写了函数

function f<X, Z extends any[]>(x: X, ...args: Z) {
  return [...args, x]
}

打字稿says 它返回any[]

有没有办法像(不支持)一样将新类型推入元组的末尾

export type PushTuple<T extends any[], X> = [...T, X];

【问题讨论】:

标签: typescript tuples


【解决方案1】:

TS4.0+ 更新

TypeScript 4.0 引入了variadic tuple types,它以更直接的方式支持将Pushing 到元组的末尾...就像这样:

type Push<T extends readonly any[], V> = [...T, V];

TS3.9 的旧答案-:

我通常根据您所称的Unshift(但我称之为Cons)来定义Push,如下所示:

type Cons<H, T extends readonly any[]> =
    ((head: H, ...tail: T) => void) extends ((...cons: infer R) => void) ? R : never;

type Push<T extends readonly any[], V>
    = T extends any ? Cons<void, T> extends infer U ?
    { [K in keyof U]: K extends keyof T ? T[K] : V } : never : never;

Push&lt;T, V&gt; 的工作方式是使元组比T 长一个元素(它与Cons 一样),然后是maps over it。它用来自T 的相应元素填充输出的初始元素,然后剩下的任何东西都填充V。长度为 n+1 的映射元组中唯一不是长度为 n 的元组的索引的元素索引是索引 n 本身,这意味着新元组的最后一个元素是V。 (我确保distribute 超过T,以防它是一个工会。)

请注意,这仅适用于非边缘情况...不要期望 readonlyoptionalrest 元组元素或非元组数组表现良好;如果你想定义它,你必须自己解决这些限制。


恢复常规答案:

那么你可以像这样定义f()

function f<X, Z extends any[]>(x: X, ...args: Z): Push<Z, X>;
function f(x: any, ...args: any[]): any[] {
    return [...args, x]
}

(请注意,我使用overload 让自己不必担心编译器会尝试并且无法理解实现符合Push&lt;Z, X&gt;

它可以按您的预期工作:

const s = f(4, "hey", false);
// const s: [string, boolean, number]
console.log(s); // ["hey", false, 4]

好的,希望对您有所帮助;祝你好运!

Link to code

【讨论】:

  • 为什么需要T extends any ?检查?
  • 这是“通过联合分配”部分...Push&lt;[1, 2] | [3], 4&gt; 变为 [1, 2, 4] | [3, 4]T extends any,正如预期的那样。没有它,你会得到never 或其他奇怪的东西。
  • 是否可以调整此解决方案以适应this
  • 4.0 解决方案应该有any[] 而不是any
猜你喜欢
  • 2015-06-25
  • 2015-08-11
  • 2018-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
相关资源
最近更新 更多