【问题标题】:Typescript is it possible to declare a generic type for an array of 1-N stringsTypescript 是否可以为 1-N 个字符串的数组声明泛型类型
【发布时间】:2020-02-19 10:27:33
【问题描述】:

在标题中有点难以解释,但基本上,我希望能够声明一个从 1 到 N 的固定长度字符串的类型数组:

interface Command {
  [key: string]: (args: [string, ...string[]]) => boolean;
}

const cmd: Command = {
  TEST: (args: [string, string]) => args[0] === args[1],
  TEST2: (args: [string]) => args[0] === 'hello'
}

所以这不起作用,因为 [string, string] 与 string[] 不同:

Type '(args: [string]) => boolean' is not assignable to type '(args: [string, ...string[]]) => boolean'.

解决方案可能是定义所有类型的参数:

interface Command {
  [key: string]: (args: [string] | [string, string] | [string, string, string]) => boolean;
}

但是对于简单的事情来说有点过于冗长(同意它可以封装在一个接口中),无论如何我没有看到另一个优雅的解决方案?

谢谢,

【问题讨论】:

  • 不,这是不可能的。 Typescript 不支持具有指定字符串长度的类型。但也许有些东西可以帮助你,看看这个答案:stackoverflow.com/a/54832231/7616528
  • 您的“冗长”解决方案也不起作用,对吧?它给出了同样的错误。我不太确定您希望Command 看起来像什么。你能说明你打算如何使用c 类型为Command 的值吗?说,你有函数c.f...你可以用c.f(["hello"])调用它吗?你能用c.f(["hello","goodbye"]) 打电话吗?

标签: typescript typescript-typings


【解决方案1】:

我怀疑您实际上需要将Command 设为generic,以便实际使用它的属性。如果你有像(arg: [string] | [string, string]) => boolean 这样的函数类型,那么你不能用(arg: [string]) => boolean(arg: [string, string]) => boolean 来实现它。函数类型在它们的参数类型中有所不同contravariantly。您可以扩大但不能缩小函数参数的类型。除非您想要求所有 Command 类型的方法必须接受 每个 长度为 1 或更大的字符串数组,否则您必须使用泛型。

这是Command 的一个可能类型,以及一个辅助函数asCommand(),它允许编译器在给定Command<T> 类型的值的情况下推断T 的正确值,而无需您自己写出来:

type Command<T> = { [K in keyof T]: (args: T[K]) => boolean }

const asCommand = <T extends Record<keyof T, [string, ...string[]]>>(
    cmd: Command<T>
) => cmd;

然后,您的cmd 常量可以这样声明而没有错误:

const cmd = asCommand({
    TEST: (args: [string, string]) => args[0] === args[1],
    TEST2: (args: [string]) => args[0] === 'hello'
});

并且编译器记得cmd.TEST 接受一对,cmd.TEST2 接受一个元组:

cmd.TEST(["", ""]); // okay
cmd.TEST([]); // error
cmd.TEST([""]); // error
cmd.TEST(["", "", ""]); // error

cmd.TEST2([""]); // okay
cmd.TEST2([]); // error
cmd.TEST2(["", ""]); // error
cmd.TEST2(["", "", ""]); // error

而且你不能给出一个只接受零长度元组的属性:

const badCmd = asCommand({
    OOPS: (args: []) => false, // error!
})

我希望这能给你一些方向;祝你好运!

Playground link to code

【讨论】:

    猜你喜欢
    • 2019-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 2015-08-20
    相关资源
    最近更新 更多