gpt4 book ai didi

typescript - Iterable> 无法确认函数中的泛型 T

转载 作者:行者123 更新时间:2023-12-05 02:07:42 25 4
gpt4 key购买 nike

这是我的问题。

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>;
}

Iterable<T>有一个符号键控方法,其返回类型为 Iterator<T> ,它本身就是 defined作为:

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相关类型的属性(property)T你正在寻找。

所以要转一个类型XIterable<T>进入T , 编译器需要做类似 Extract<ReturnType<ReturnType<X[typeof Symbol.iterator]>['next']>, { done?: false }>['value'] 的事情.

我认为可能存在一些深度限制,在该限制之后编译器会放弃尝试推断事物。你可以看到推断 T来自 Iterable<T>有效(可能有 5 或 6 层嵌套),但推断 T来自 Iterable<Iterable<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[]>  

现在看起来不错!好的,希望有所帮助;祝你好运!

Playground link to code

关于typescript - Iterable<Iterable<T>> 无法确认函数中的泛型 T,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61506176/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com