Iterable<;Iterable<;T>;>;无法确认函数中的泛型T [英] Iterable<Iterable<T>> cannot confirm generic T in function
本文介绍了Iterable<;Iterable<;T>;>;无法确认函数中的泛型T的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
这是我的问题。
const iterable = [[[1,2,3]]]
function flat<T>(t:Iterable<Iterable<T>>):Iterable<T>{
return [...t][0]
}
const flatted = flat(iterable) //return Iterable<unknown>
上面的函数不能假设T为数字,只能将其断言为未知。
此时此刻,我认为‘嗯……不能推断仿制药中的仿制药?’但在下面的代码中,Chuck运行良好
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
的类型是defined in the relevant library:
interface Iterable<T> {
[Symbol.iterator](): Iterator<T>;
}
anIterable<T>
有一个带符号键的方法,其返回类型为Iterator<T>
,其本身为definedas:
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, ...>
,即defined为区分的联合类型
type IteratorResult<T, TReturn = any> = IteratorYieldResult<T> | IteratorReturnResult<TReturn>;
谁的members
interface IteratorYieldResult<TYield> {
done?: false;
value: TYield;
}
interface IteratorReturnResult<TReturn> {
done: true;
value: TReturn;
}
,其中只有一个具有您试图查找的相关类型的value
属性。
Iterable<T>
的类型X
转换为T
,编译器需要执行类似Extract<ReturnType<ReturnType<X[I]>['next']>, { done?: false }>['value']
的操作(其中I
是一个虚构的可索引[Symbol.iterator]
属性,由于类型脚本中的错误,我们不能自己编写该属性;microsoft/TypeScript#24622)。
我认为可能存在某个深度限制,超过该限制后,编译器将放弃尝试推断。您可以看到T
从Iterable<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[]>
现在看起来不错!好的,希望这会有帮助;祝你好运!
这篇关于Iterable<;Iterable<;T>;>;无法确认函数中的泛型T的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文