typescript - TypeScript 3.5 和 3.6 之间的泛型参数推断不匹配
问题描述
我试图理解以下代码的类型检查:
const marker = Symbol();
type ConstItem = string | number | null;
type Item = ConstItem | { [index: string]: string };
type WrapOrConst<T extends Item> = Wrap<T> | (T extends ConstItem ? T : never);
type Wrap<T extends Item> = {
__marker: typeof marker,
__phantom: T;
}
declare function wrapped<T extends Item>(item: T): Wrap<T>;
declare function str(): string;
type UnionInner<T extends Array<WrapOrConst<Item>>> = T extends Array<WrapOrConst<infer U>> ? U : never;
declare function Union<T extends WrapOrConst<Item>[]>(...inner: T): Wrap<UnionInner<T>>;
const test = Union(wrapped(str()), null);
const test2: string | null = test.__phantom;
这在 TypeScript 3.6 中运行良好,但在 TypeScript 3.5 中失败,因为test
推断为 beWrap<Item>
和 not Wrap<string | null>
。我无法在发行说明中找到任何内容;它只是一个错误吗?我可以在早期版本中以某种方式解决这个问题(理想情况下,直到 TypeScript 3.1)?
解决方案
是的,它被认为是一个错误 ( microsoft/TypeScript#32434 ),其中涉及某些联合的泛型类型参数推断会产生不良结果。如您所见,TypeScript 3.6已修复 (microsoft/TypeScript#32460)。
要使您的代码在以前的版本中工作,您可能必须重构以在推理站点中包含更少的显式联合,如下所示:
type Unwrap<U extends Item | Wrap<Item>> = U extends Wrap<infer I> ? I : U
declare function Union<T extends WrapOrConst<Item>[]>(...inner: T): Wrap<Unwrap<T[number]>>;
这似乎表现得像你想要的那样:
const test = Union(wrapped(str()), null).__phantom; // string | null
但是,我当然不知道您拥有的全部用例,因此可能存在一些边缘情况,其中所需的行为与上述行为不同。但这应该有希望让您了解如何进行。
好的,希望有帮助;祝你好运!
推荐阅读
- c - printf() 正在打印错误的值
- java - 线程“main”中的异常 java.util.InputMismatchException 错误但程序仍在运行
- python - 试图从列表中删除数字字符,字符不会删除,我不知道为什么
- c# - 当集合类型 DP 发生变化时如何通知我?
- php - Helvetica 不支持订阅号
- javascript - Fetch API:处理错误的 URL
- python - 为什么自动编码器与编码器 + 解码器的预测不同?
- django - Django REST 保存图像但返回错误路径
- react-native - 使用将根据条件从另一个 api 获取数据的参数反应本机?
- ffmpeg - 是否可以在 ffmpeg 的 -filter_complex 选项中同时使用 vidstabdetect 和 vidstabtransform ?