[英]Typescript conditional void parameter type
I was trying to implement a custom Error class, which would accept different kinds of data depending on the error code.我试图实现一个自定义错误 class,它将根据错误代码接受不同类型的数据。 I was pretty sure that was I wanted to do was too complex for typescript to infer, but, to my surprise, this worked:我很确定我想做的事情太复杂了,以至于 typescript 无法推断,但令我惊讶的是,这行得通:
const enum ERROR_CODES {
E_AUTHORIZATION = 'Authorization error',
E_REQUEST = 'Request failed',
E_INVALID = 'Invalid data',
}
interface ERROR_TYPES {
[ERROR_CODES.E_AUTHORIZATION]: string
[ERROR_CODES.E_REQUEST]: { url: string; status: number }
[ERROR_CODES.E_INVALID]: { action: string; field: string }
}
class MyError<TError extends ERROR_CODES> extends Error {
constructor(
public readonly code: TError,
public readonly data: ERROR_TYPES[TError],
) { super(code) }
}
Now I can use it like this:现在我可以像这样使用它:
throw new MyError(ERROR_CODES.E_AUTHORIZATION, 'whatever')
throw new MyError(ERROR_CODES.E_AUTHORIZATION, {
operation: 'login',
field: 'email',
})
This works fine.这工作正常。 Another thing I wanted to do is to create such error codes that need no data.我想做的另一件事是创建不需要数据的错误代码。 Since it is possible to define functions like this:因为可以定义这样的函数:
function foo(bar: void) {}
foo()
My next logical step was to write this:我的下一个合乎逻辑的步骤是写这个:
const enum ERROR_CODES {
// ...
E_UNKNOWN = 'Unknown error'
}
interface ERROR_TYPES {
// ...
[ERROR_CODES.E_UNKNOWN]: void
}
Now typescript behaves in quite a strange way.现在 typescript 表现得非常奇怪。 If I write this:如果我写这个:
throw new MyError(ERROR_CODES.E_UNKNOWN, undefined)
it works.有用。 If I write this:如果我写这个:
throw new MyError(ERROR_CODES.E_UNKNOWN)
it says Expected 2 arguments, but got 1.
.它说Expected 2 arguments, but got 1.
. If I write something like this:如果我写这样的东西:
throw new MyError(ERROR_CODES.E_UNKNOWN, void 0)
which should basically be the same as the first example, then it says Expected 'undefined' and instead saw 'void'.
这应该与第一个示例基本相同,然后它说Expected 'undefined' and instead saw 'void'.
. . What is happening here and is it possible to make the second example work with just one argument?这里发生了什么,是否可以使第二个示例仅使用一个参数?
I can't reproduce "expected undefined
but instead saw void
".我无法重现“预期undefined
但看到void
”。
Here's how I might approach what you're trying to do.以下是我可能会如何处理您正在尝试做的事情。 To "optionally make a function parameter optional", I'd represent the parameter list as as rest tuple .为了“可选地使 function 参数可选”,我将参数列表表示为rest tuple 。 Consider this type alias:考虑这种类型别名:
type UndefParamToOptional<T> = undefined extends T ? [T?] : [T];
The type UndefParamToOptional<string>
is just [string]
, but UndeParamToOptional<string | undefined>
UndefParamToOptional<string>
类型只是[string]
,但UndeParamToOptional<string | undefined>
UndeParamToOptional<string | undefined>
is [string?]
. UndeParamToOptional<string | undefined>
是[string?]
。 That's a tuple with a single optional element corresponding to an optional function parameter.这是一个具有单个可选元素的元组,对应于可选的 function 参数。 Then we can implement MyError
like this:然后我们可以像这样实现MyError
:
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;
}
}
I'm using a single overload signature to show how you intend to call it, while leaving the implementation signature unchanged.我使用单个重载签名来显示您打算如何调用它,同时保持实现签名不变。
Now this should behave as you expect:现在这应该如您所愿:
throw new MyError(ERROR_CODES.E_UNKNOWN); // okay
Hope that helps.希望有帮助。 Good luck!祝你好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.