[英]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];
}
至此,一切似乎都正常了。 当使用cmd2
为exec
编写args时,我可以看到编译器(打字稿)为3个args提供了类型信息。 返回值也是正确的...
但是,事情在包含声明...rest: U
的那一行发生了变化...rest: U
rest参数为...rest: U
错误很简单: A rest parameter must be of an array type.
问题
U
必须是一个数组。 我们知道U
是P
的值,但不能保证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');
在编写...rest
, rest
是一个数组:
const someFunction = (...args) => console.log(args); someFunction('hello', 'world');
因此,您应该这样写:
(command: E, ...rest: U[])
或任何适合您程序所需行为的类似内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.