[英]How do I have typescript have the type properly infered when using a generic initializer function?
I have a function that may take a parameter in the form of a callable like this:我有一个 function 可以采用这样的可调用形式的参数:
type Initial<T> = T | PromiseLike<T> | (() => T) | (() => PromiseLike<T>)
const usePromise = <T>(initial: Initial<T>): T => {
let result: unknown = null
/* ... */
return result as T
}
If the type of initial
is something like Promise<number>
or PromiseLike<number>
, typescript correctly infers the type of T
as number
.如果
initial
的类型类似于Promise<number>
或PromiseLike<number>
,则 typescript 会正确地将T
的类型推断为number
。 However, if initial
is of a function type like () => PromiseLike<number>
, typescript infers T
as PromiseLike<number>
.但是,如果
initial
是 function 类型,如() => PromiseLike<number>
,则 typescript 将T
推断为PromiseLike<number>
。 For example:例如:
// good:
const initial1 = new Promise<number>(() => null)
const result1 = usePromise(initial1) // result1: number (OK)
// bad:
const initial2: () => PromiseLike<number> = () => new Promise(() => null)
const result2 = usePromise(initial2) // result2: PromiseLike<number> (ERROR, should be number)
Note: obviously these promises would never resolve nor reject, but this question is purely about the type inference.注意:显然这些承诺永远不会解决或拒绝,但这个问题纯粹是关于类型推断的。
How do I get typescript to also correctly infer the type in the second example?如何让 typescript 也正确推断第二个示例中的类型?
The union presents multiple valid inference targets.该联合提供了多个有效的推理目标。 The singular
T
type is allways valid and TypeScript propably does not put in the computation effort to see that (() => PromiseLike<T>)
is also a valid target.单数
T
类型始终有效,并且 TypeScript 可能不会进行计算以查看(() => PromiseLike<T>)
也是一个有效目标。 We need to explicitly give an inference order to make the compiler examine more specific types like (() => PromiseLike<T>)
first.我们需要明确给出一个推理顺序,让编译器首先检查更具体的类型,例如
(() => PromiseLike<T>)
。 I would suggest the use of overloads.我建议使用重载。
The overloads are resolved in order.重载按顺序解决。 The first overload is examined before the second one etc...
第一个过载在第二个过载之前被检查等等......
type Initial<T> = T | PromiseLike<T> | (() => T) | (() => PromiseLike<T>)
function usePromise<T>(initial: (() => PromiseLike<T>)): T
function usePromise<T>(initial: (() => T)): T
function usePromise<T>(initial: PromiseLike<T>): T
function usePromise<T>(initial: T): T
function usePromise<T>(initial: Initial<T>): T {
let result: unknown = null
/* ... */
return result as T
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.