[英]How does the type defination of `promise.all` work well in this case?
我在做一道type-challenges的題的時候發現了這個問題。
以下代碼在情況 3 中將失敗:
declare function PromiseAll<A extends readonly unknown[]>(values: A): Promise<{
-readonly [key in keyof A]: Awaited<A[key]>
}>
// test
const promiseAllTest3 = PromiseAll([1, 2, Promise.resolve(3)])
// except Promise<[number, number, number]>, but got Promise<number[]>
但是當我將通用readonly unknown[]
更改為(readonly unknown[]) | []
(readonly unknown[]) | []
像下面這樣,一切都會好的。
declare function PromiseAll<A extends (readonly unknown[]) | [] /* change here */>(values: A): Promise<{
-readonly [key in keyof A]: Awaited<A[key]>
}>
// test
const promiseAllTest3 = PromiseAll([1, 2, Promise.resolve(3)]) // Promise<[number, number, number]>
我不明白為什么向通用“A”添加“[]”約束會影響案例 3。我根本無法將它們關聯起來。
另外,正確的實現是我在vscode中找到的lib.es2015.promise.d.ts的標准實現
// lib.es2015.promise.d.ts
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T extends readonly unknown[] | []>(values: T): Promise<{ -readonly [P in keyof T]: Awaited<T[P]> }>;
我發現這段代碼工作正常。 因為它通過轉換為 Tuple 來保留所有類型及其位置:
declare function PromiseAll<A extends any[]>(values: readonly [...A]): Promise<{
[key in keyof A]: Awaited<A[key]>
}>
基本上它是窄元組[number, number, number]
類型而不是加寬數組number[]
因為添加... | []
... | []
到類型,將文字類型[]
添加到定義返回類型的上下文中,在本例中為通用A
。
這是詳細解釋/實現正在發生的事情的 PR: GitHub
並且您的代碼是 PR 中引入的以下更改的完美示例:
為數組文字中的元素推斷的類型是表達式的擴展文字類型,除非該元素具有包含文字類型的上下文類型。
PromiseAll
的返回類型在A
的上下文中定義。 A
又在其定義中使用文字類型。 因此它構成了一個“包含文字類型的上下文類型”,阻止了從元組到數組的類型擴展。
作為傳遞給函數的數組文字的默認推斷行為,TypeScript 團隊選擇推斷數組類型而不是元組類型。
如果將鼠標懸停在函數調用上,您可以在工具提示中看到它:
declare function PromiseAll<A extends readonly unknown[]>(values: A): void
PromiseAll([1, 2, Promise.resolve(3)])
// function PromiseAll<(number | Promise<number>)[]>(...)
A
的類型被推斷為數組類型(number | Promise<number>)[]
而不是元組類型[number, number, Promise<number>]
。
這種行為在大多數情況下都可以正常工作,但要正確鍵入Promise.all()
函數,我們需要推斷元組類型。 有多種方法可以做到這一點,您在問題中發現了其中兩種。
但是為什么這兩種方法都可以推斷出元組類型呢? 我們可以在#31434中從ahejlsberg得到澄清
我們僅在上下文類型是或包含類似元組的類型時推斷元組類型
這幾乎是最重要的一點。 (readonly unknown[]) | []
(readonly unknown[]) | []
起作用是因為約束中的聯合現在包含一個元組類型[]
。 這足以提示編譯器推斷元組類型。
使用readonly [...A]
也可以推斷元組,因為它使用的是4.0中引入的可變元組語法。 有關使用可變元組類型進行推理的詳細說明,請參閱PR/#39094 。
當數組文字的上下文類型是元組類型時,將為數組文字推斷出元組類型。 類型 [...T],其中 T 是類似數組的類型參數,可以方便地用於指示對元組類型推斷的偏好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.