繁体   English   中英

TypeScript中的强类型休息参数

[英]Strongly typed rest parameters in TypeScript

如何使用TypeScript 3.2定义动态的强类型休息参数? 这是我的用例:

function exec<T, P extends ICommandNameArgumentTypeMapping, E extends keyof P, U extends P[E]>(command: E, ...rest: U): U{
    return;
}

exec('cmd2', true, 1, 'hello');

interface ICommandNameArgumentTypeMapping {
    ['cmd1']: [string];
    ['cmd2']: [boolean, number, string];
    ['cmd2']: [boolean, boolean];
}

至此,一切似乎都正常了。 当使用cmd2exec编写args时,我可以看到编译器(打字稿)为3个args提供了类型信息。 返回值也是正确的...

但是,事情在包含声明...rest: U的那一行发生了变化...rest: U rest参数为...rest: U

错误很简单: A rest parameter must be of an array type.

问题

U必须是一个数组。 我们知道UP的值,但不能保证P所有值都是数组。 这是因为exec并不依赖于下面定义的具体ICommandNameArgumentTypeMapping接口,而是依赖于我们尚不完全了解的某些P 而且因为我们还不知道它,所以我们不能相信它遵循ICommandNameArgumentTypeMapping的蓝图—毕竟,它可能会添加一些自己的属性,这些属性不是数组。

解决方案是确保所有值(现在和将来)始终是数组。

interface ICommandNameArgumentTypeMapping {
    ['cmd1']: [string];
    ['cmd2']: [boolean, number, string];
    ['cmd3']: [boolean, boolean];
    [index: string]: any[]
}

该额外的属性称为索引签名

当然,您可以在这里更加精确地说(string | number | boolean)[]而不是any[]

奖励积分

您的代码中还有其他一些错误:

  • 计算的属性名称cmd2已重复
  • T类型参数未使用
  • P类型参数使用不正确(既不用于描述参数也不用于返回类型)
  • exec承诺返回U ,但是返回undefined

更正的解决方案:

function exec<P extends ICommandNameArgumentTypeMapping, E extends keyof P, U extends P[E]>(mapping: P, command: E, ...rest: U): U{
    return rest;
}

interface ICommandNameArgumentTypeMapping {
    ['cmd1']: [string];
    ['cmd2']: [boolean, number, string];
    ['cmd3']: [boolean, boolean];
    [index: string]: any[]
}

declare const mapping: ICommandNameArgumentTypeMapping;

exec(mapping, 'cmd2', true, 1, 'hello');

问题是P extends ICommandNameArgumentTypeMapping ,这意味着exec()接受作为已定义接口的超集的任何映射。 这将允许非数组类型。 如果删除该约束(并修复我认为是错字的内容),则不会收到任何错误消息。

interface ICommandNameArgumentTypeMapping {
    ['cmd1']: [string];
    ['cmd2']: [boolean, number, string];
    ['cmd3']: [boolean, boolean];
}

type P = ICommandNameArgumentTypeMapping;

function exec<T, E extends keyof P, U extends P[E]>(command: E, ...rest: U): U{
    return rest;
}

exec('cmd2', true, 1, 'hello');

在编写...restrest是一个数组:

 const someFunction = (...args) => console.log(args); someFunction('hello', 'world'); 

因此,您应该这样写:

(command: E, ...rest: U[])

或任何适合您程序所需行为的类似内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM