英文:
Why Promise.reject().catch(() => 5) valid for Typescript
问题
The TypeScript compiler doesn't complain about this statement because the catch
method in TypeScript's Promise interface allows for a wide range of return types. It assumes that the handler function returns TResult | PromiseLike<TResult>
where TResult = never
, but in your example, the handler function returns 5
, which is a number
. This might seem unusual, but TypeScript doesn't enforce strict type checking in this case because it's valid for the handler to return a non-Promise value like 5
. However, you're correct that 5
is not a PromiseLike
because it doesn't have a .then
function.
英文:
Could you help me understand why TS compiler doesn't complain about this statement?
Promise.reject().catch(() => 5)
If checking the definition of the handler function inside the catch
we can see the piece of code as follows:
interface Promise<T> {
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
}
It assumes that the handler function returns TResult | PromiseLike<TResult>
where TResult = never
. And then in my example a handler function returns 5
which is a number
. So I could assume that 5
is never | PromiseLike<never>
. But it is not the case. A number
doesn't have .then
function so it's not a PromiseLike
.
Thanks!
答案1
得分: 1
TypeScript不会抱怨,因为catch()
方法中的类型参数TResult
在定义中只默认为never
。类型参数TResult
没有以任何方式被限制为never
。
请注意,在类型参数声明中的=
运算符是默认类型参数,而类型参数声明中的extends
运算符是类型参数约束。通常情况下,你可以选择使用它们中的任何一个或两者兼用。在调用签名中的类型参数声明,例如<T extends C = D>(⋯) => ⋯
意味着T
必须可分配给C
,如果无法推断出T
,它将默认为D
(D也必须可分配给约束C
)。如果省略了C
,则等同于指定它为未知类型,如果省略了D
,则等同于指定它为C
。所以<TResult = never>
等同于<TResult extends unknown = never>
,意味着它默认为never
,但没有任何约束。
所以:只有在无法从输入中推断出TResult
时,才会回退到never
,例如如果未提供onrejected
参数。但是您确实提供了一个onrejected
参数为() => 5
。因此,TypeScript能够推断TResult
类型参数为number
,因为() => 5
是一个有效的 ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null
。您可以通过在启用 IntelliSense 的 IDE 中将鼠标悬停在catch
调用上来验证这一点:
Promise.reject().catch(() => 5)
// (method) Promise<never>.catch<number>(
// onrejected?: ((reason: any) => number | PromiseLike<number>) | null | undefined
// ): Promise<number>
所以一切都按照预期和意图工作。
英文:
TypeScript doesn't complain because the type parameter TResult
in that definition of catch()
method just defaults to never
. The type parameter TResult
is not constrained to never
in any way.
Note that the =
operator inside a type parameter declaration is a default type argument, while the extends
operator inside a type parameter declaration is a type parameter constraint. In general you can have neither or either or both. A type parameter declaration on a call signature like <T extends C = D>(⋯) => ⋯
means that T
must be assignable to C
, and if T
cannot be inferred, it will default to D
(which must also be assignable to the constraint C
). If you leave out C
then it is equivalent to specifying it as the unknown
type, and if you leave out D
then it is equivalent to specifying it as C
. So <TResult = never>
is equivalent to <TResult extends unknown = never>
, meaning it defaults to never
but is not constrained at all.
So: TResult
will only fall back to never
in the event that it cannot be inferred from the input, such as if the onrejected
argument is not supplied. But you did supply an onrejected
argument of () => 5
. And thus TypeScript was able to infer the TResult
type argument as number
, because () => 5
is a valid ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null
. You can verify this by hovering over the catch
call in an IntelliSense-enabled IDE:
Promise.reject().catch(() => 5)
// (method) Promise<never>.catch<number>(
// onrejected?: ((reason: any) => number | PromiseLike<number>) | null | undefined
// ): Promise<number>
So everything's working as expected and intended here.
答案2
得分: 0
由于回调函数返回值为5,catch() 创建的新 Promise 对象将以该值解决。也就是说,catch() 创建的新 Promise 对象将以值5解决,因为回调函数返回该值。
英文:
Since the callback function returns a value of 5, the new promise created by catch() is resolved with that value. Meaning, the new promise created by catch() is resolved with the value of 5 because the callback function returns that value.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论