[英]Iterable<Iterable<T>> cannot confirm generic T in function
這是我的問題。
const iterable = [[[1,2,3]]]
function flat<T>(t:Iterable<Iterable<T>>):Iterable<T>{
return [...t][0]
}
const flatted = flat(iterable) //return Iterable<unknown>
以上 function 不能假設 T 為數字,只需將其斷言為未知。 此時此刻,我堅持認為“嗯……不能推斷出泛型中的泛型?”。 但是下面的代碼卡盤效果很好
const iterable = [[[1,2,3]]]
function flat<T>(t:Array<Array<T>>):Array<T>{
return [...t][0]
}
const flatted = flat(iterable) // omg.. return Array<number>
還
const iterable = [[[1,2,3]]]
function flat<T>(t:Iterable<Array<T>>):Array<T>{
return [...t][0]
}
const flatted = flat(iterable) // also works.. return Array<number>
它們之間有什么區別? 感謝您閱讀我的問題。
呸,是的,我看到默認推理不足以將Iterable<Iterable<T>>
展開到T
中。 如果您查看相關庫中如何定義Iterable
的類型,這並不奇怪:
interface Iterable<T> {
[Symbol.iterator](): Iterator<T>;
}
Iterable<T>
有一個符號鍵控方法,其返回類型為Iterator<T>
,它本身定義為:
interface Iterator<T, TReturn = any, TNext = undefined> {
next(...args: [] | [TNext]): IteratorResult<T, TReturn>;
return?(value?: TReturn): IteratorResult<T, TReturn>;
throw?(e?: any): IteratorResult<T, TReturn>;
}
其中所有方法都返回IteratorResult<T, ...>
,它被定義為可區分的聯合類型
type IteratorResult<T, TReturn = any> = IteratorYieldResult<T> | IteratorReturnResult<TReturn>;
其成員是
interface IteratorYieldResult<TYield> {
done?: false;
value: TYield;
}
interface IteratorReturnResult<TReturn> {
done: true;
value: TReturn;
}
其中只有一個具有您要查找的相關類型T
的value
屬性。
因此,要將Iterable<T>
的X
類型轉換為T
,編譯器需要執行類似Extract<ReturnType<ReturnType<X[I]>['next']>, { done?: false }>['value']
(其中I
是一個虛構的可索引[Symbol.iterator]
屬性,由於 TypeScript; microsoft/TypeScript#24622中的錯誤,我們無法自己編寫它)。
我認為可能存在一些深度限制,之后編譯器會放棄嘗試推斷事物。 您可以看到從Iterable<T>
推斷T
是可行的(可能大約有 5 或 6 層嵌套),但從Iterable<Iterable<T>>
推斷T
太深了(10 或 12 層?):
type N = number[][] extends Iterable<infer T> ? T : never; // number[] 👍
type O = number[][] extends Iterable<Iterable<infer T>> ? T : never; // unknown 👎
這導致我采用以下解決方法:創建一個類型別名以顯式操作一層Iterable
,然后使用它兩次:
type DeIterable<T extends Iterable<any>> = T extends Iterable<infer U> ? U : never;
你可以看到這個作品:
type Okay = DeIterable<DeIterable<number[][]>>; // number 👍
現在flat()
可以這樣定義:
function flat<II extends Iterable<Iterable<any>>>(
t: II
): Iterable<DeIterable<DeIterable<II>>> {
return [...t][0]
}
其中輸入值是泛型類型II
,我們在其上使用DeIterable
兩次以獲得您之前想要的T
:
const flatted = flat(iterable) //return Iterable<number[]>
看起來不錯,現在,好吧; 希望有幫助; 祝你好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.