Typescript条件void参数类型

Typescript条件void参数类型,typescript,types,Typescript,Types,我试图实现一个自定义错误类,该类将根据错误代码接受不同类型的数据。我很确定我想做的是太复杂了,typescript无法推断,但是,令我惊讶的是,这起作用了: 常量枚举错误\u代码{ E_授权='授权错误', E_请求='请求失败', E_INVALID='无效数据', } 接口错误类型{ [错误代码.E\u授权]:字符串 [错误代码.E_请求]:{url:string;状态:number} [错误代码.E_无效]:{action:string;field:string} } 类MyError扩展

我试图实现一个自定义错误类,该类将根据错误代码接受不同类型的数据。我很确定我想做的是太复杂了,typescript无法推断,但是,令我惊讶的是,这起作用了:

常量枚举错误\u代码{
E_授权='授权错误',
E_请求='请求失败',
E_INVALID='无效数据',
}
接口错误类型{
[错误代码.E\u授权]:字符串
[错误代码.E_请求]:{url:string;状态:number}
[错误代码.E_无效]:{action:string;field:string}
}
类MyError扩展了错误{
建造师(
公共只读代码:恐怖,
公共只读数据:错误类型[恐怖],
){super(code)}
}
现在我可以这样使用它:

class MyError<TError extends ERROR_CODES> extends Error {
  constructor(
    code: TError,
    ...[data]: UndefParamToOptional<ERROR_TYPES[TError]>
  );
  constructor(public readonly code: TError, public readonly data: ERROR_TYPES[TError]) {
    super(code);
    this.data = data;
  }
}
抛出新的MyError(错误\u code.E\u授权,'whatever')
抛出新的MyError(错误代码.E\U授权,{
操作:“登录”,
字段:“电子邮件”,
})
这个很好用。我想做的另一件事是创建这种不需要数据的错误代码。因为可以这样定义函数:

class MyError<TError extends ERROR_CODES> extends Error {
  constructor(
    code: TError,
    ...[data]: UndefParamToOptional<ERROR_TYPES[TError]>
  );
  constructor(public readonly code: TError, public readonly data: ERROR_TYPES[TError]) {
    super(code);
    this.data = data;
  }
}
函数foo(bar:void){
foo()
我的下一个逻辑步骤是写以下内容:

常量枚举错误\u代码{
// ...
E_UNKNOWN='未知错误'
}
接口错误类型{
// ...
[错误代码.未知]:无效
}
现在,typescript的行为非常奇怪。如果我这样写:

抛出新的MyError(错误代码未知,未定义)
它起作用了。如果我这样写:

抛出新的MyError(错误代码未知)
它说
需要2个参数,但得到1个。
。如果我这样写:

class MyError<TError extends ERROR_CODES> extends Error {
  constructor(
    code: TError,
    ...[data]: UndefParamToOptional<ERROR_TYPES[TError]>
  );
  constructor(public readonly code: TError, public readonly data: ERROR_TYPES[TError]) {
    super(code);
    this.data = data;
  }
}
抛出新的MyError(错误代码未知,无效0)
这应该与第一个示例基本相同,然后它说
预期为“未定义”,而看到的是“void”。
。这里发生了什么,第二个示例是否可以只使用一个参数工作?

我无法重现“预期的
未定义的
,而是看到了
无效的


下面是我可能会如何处理你试图做的事情。为了“可选地使函数参数成为可选的”,我将参数列表表示为。考虑这种类型别名:

type UndefParamToOptional<T> = undefined extends T ? [T?] : [T];
我使用单个签名来显示您打算如何调用它,同时保持实现签名不变

现在,它的行为应该与您预期的一样:

throw new MyError(ERROR_CODES.E_UNKNOWN); // okay
希望有帮助。祝你好运


哇,太酷了!我也意识到我有点误解了重载是如何工作的。谈到
预期为“未定义”,但看到“void”
错误,此消息显示在vscode中。不知道为什么会发生这种情况,因为我使用的版本与TS Playerd相同,而且我认为他们没有实现自己的编译器。不管怎样,那没那么重要,谢谢!