是否有一个处理 T | 的打字稿泛型T[]| “*”

问题描述 投票:0回答:1

我对打字稿中的泛型很陌生,这很令人困惑

有没有办法让

spread operator ...
在下面的代码片段中工作

问题

这条线

[ key: U, ...rest: Reg[U] ]
,没有像我预期的那样工作

问题

我做错了什么?

我试图让这项工作成功,但失败了

我还没有尝试过的可能解决方案

函数重载


type Registery = {
  "item.1": [name: string]
  "item.2": [id: number, ready: "Y" | "N"]
  "item.3": [ok: boolean]
}
type ReK = keyof Registery
const send = <
  T extends ReK | ReK[] | "*" | never = never
>(
  key: T,
  callback: (
    ...args: 
        T extends Array<infer U>
          ? (
            U extends ReK 
              ? [ key: U, ...rest: Registery[U] ]
              : never 
          )
          : T extends string 
            ? (
              T extends ReK 
                ? Registery[T]
                : T extends "*" 
                  ? Registery[ReK]
                  : never 
            )
            : never 
  ) => any
) => { /**  */ }
send("item.2", (...args) => {
  const [ 
    arg1,
    //^?const arg1: number 
    arg2,
    //^?const arg2: "Y" | "N" 
  ] = args 
})

send(["item.1", "item.2"], (key, ...args) => {
  //                                ^?
  const k = key 
  //    ^?const k: "item.1" | "item.2"

  if (key == "item.1") {
    const [ 
      arg1,
      //^?const arg1: string | number 
      arg2, 
      //^?const arg1: string | number 
    ] = args
  }
  if (key == "item.2") {
    const [ 
      arg1,
      //^?const arg1: string | number 
      arg2,
      //^?const arg2: string | number 
    ] = args 
  }
})

这是 ts Playground 的链接 https://tsplay.dev/mxEQ7W

typescript generics overloading spread
1个回答
0
投票

你的类型没问题。问题是,当使用“rest 属性”进行解构时,TypeScript 不支持“解构可区分联合”。 microsoft/TypeScript#46680 有一个开放的功能请求来支持这一点,但在实现之前,您必须解决它。 你所做的相当于

type ParamUnion = [key: "item.1", name: string] | [key: "item.2", id: number, ready: "Y" | "N"]; const f: (...args: ParamUnion) => any = (key, ...rest) => { if (key === "item.1") { rest[0].toUpperCase(); // error! } else { rest[0].toFixed(); // error! } };

其中

ParamUnion
元组类型

可判别联合
,其中第一个元素是判别式。 这正是您遇到的问题,没有提及泛型或T | T[] | "*"

[ key: U, ...rest: Reg[U] ]

。那东西很有趣,但本质上是一个“红鲱鱼”。


解决此问题的一种方法是在将 
ParamUnion 类型解构分配到参数中时不使用剩余元素:

const g: (...args: ParamUnion) => any = (key, nameOrId, ready?) => { if (key === "item.1") { nameOrId.toUpperCase(); // okay } else { nameOrId.toFixed(); // okay } };

解决此问题的另一种方法是根本不解构其余元素,而只需使用

rest 参数

const h: (...args: ParamUnion) => any =
  (...args) => {
    if (args[0] === "item.1") {
      args[1].toUpperCase(); // okay
    } else {
      args[1].toFixed(); // okay
    }
  };

这两个行为都符合预期。

Playground 代码链接

    

© www.soinside.com 2019 - 2024. All rights reserved.