我正在尝试执行以下操作(也see it on TypeScript playground),但是在函数的返回类型上收到错误消息,告诉我无法将条件类型分配给联合:
type RequestType =
| 'foo'
| 'bar'
| 'baz'
interface SomeRequest {
id: string
type: RequestType
sessionId: string
bucket: string
params: Array<any>
}
type ResponseResult = string | number | boolean
async function sendWorkRequest<T extends RequestType>(
type: T,
...params
): Promise<
T extends 'foo'
? string
: T extends 'bar'
? number
: T extends 'baz' ? boolean : never
> {
await this.readyDeferred.promise
const request: SomeRequest = {
id: 'abc',
bucket: 'bucket',
type,
sessionId: 'some session id',
params: [1,'two',3],
}
const p = new Promise<ResponseResult>((/*...*/) => {/*...*/})
this.requests[request.id] = p
this.worker.postMessage(request)
return p // <-------------------------------- ERROR
}
基本上,我希望条件类型导致ResponseResult
类型之一。因此,基于传递给函数的type
参数,它应返回ResponseResult
联合中的一种类型(作为Promise)。
如何进行这项工作,以使type
参数的类型确定返回的Promise的类型?
这里是another way,它没有条件类型,但是我想知道是否可以使用type
参数的条件类型来完成它。
编辑:基于以下Erik的回答,我也很好奇this one为什么行不通,以及是否有可能在不重新定义ResponseResult
且不更改返回值的情况下使其工作的问题。功能。
@Erik,second example。
答案 0 :(得分:2)
您需要将类型封装为(假设)打字稿不能假定(计算)两个未引用的条件类型相同。
所以相反
type ResponseResult<T> =
T extends 'foo'
? string
: T extends 'bar'
? number
: T extends 'baz' ? boolean : never;
现在您可以将函数的签名更改为:
async function sendWorkRequest<T extends RequestType>(
type: T,
...params
): Promise<ResponseResult<T>> {
并更新p
:
const p = new Promise<ResponseResult<T>>(() => { });
您知道为什么或如何在不更改返回类型且不修改返回类型的定义的情况下这样做吗?
否,因为Conditional Type
不等于Type
。
在调用函数的地方是否需要显式类型转换?
不,我可以使用类型为type的属性来模拟promise,并查看它是否属于该类型:
有没有办法使其安全(无类型转换)?
不必要
答案 1 :(得分:1)
或者,为了获得类型推断的作用,您可以提供覆盖声明:
type ResponseResult = string | number | boolean
async function sendWorkRequest(type: 'foo', ...params): Promise<string>
async function sendWorkRequest(type: 'bar', ...params): Promise<number>
async function sendWorkRequest(type: 'baz', ...params): Promise<boolean>
async function sendWorkRequest(type: RequestType, ...params): Promise<ResponseResult> {
/* ... */
const p = new Promise<ResponseResult>((/* ... */) => {/* ... */})
/* ... */
}
// WORKS
async function test1() {
const result = await sendWorkRequest('foo')
result.split('')
}
test1()