【发布时间】:2021-01-04 17:29:20
【问题描述】:
我正在寻找有关类型推断的一些帮助,以根据条件类型缩小 TypeScript 中的联合。
我们的 API 采用一组参数并对其进行验证。作为验证过程的一部分,它会将所有值标准化,以便于下游处理。其中一个参数可以是字符串数组或字符串数组。规范化后,该值始终转换为字符串数组。
为了避免必须显式写出每个已验证的类型(并维护它们),我试图从传入参数(具有相同的键)和解析值推断出已验证的参数。例如:
type IncomingParams = {
names: string[] | Array<string[]> | undefined
ages: string[] | undefined
}
// Post validation the object is the following
type Validated = {
names: Array<string[]>
ages: string[]
}
这是我想出的,但它并没有确保当有联合时,它总是解析为一个数组数组。
type ArrayUnion<T> = T[] | T[][];
type Params = {
names: ArrayUnion<string>
ages: string[]
}
type ValidatedParams<P> = {
[K in keyof P]: P[K] extends ArrayUnion<infer U>
? U[][]
: NonNullable<P[K]>;
};
const validated: ValidatedParams<Params> = {} as any;
validated.names // This should be string[][]
validated.ages // This should be string[]
可能是 Typescript 无法区分联合,所以我探索的一个选项是使用 & { readonly _sym: unique symbol } 来唯一标识ArrayUnion,尽管这种方法也没有奏效。
如有任何帮助,我将不胜感激。
【问题讨论】:
-
使用您的代码,如果我将
validated.names分配给一个变量(例如const test = validated.names),它似乎具有预期的string[][]类型。 -
嗨@AlbertoRivera,谢谢。我已经把一个操场放在一起了。奇怪的是我得到了我在本地记录的错误,但是使用操场我得到了 string[[] - 但是,
ages属性也是 string[][] 当它应该是 string[] -
@J-R 根据您在上述评论中提供的信息,它让我相信您的工作区/项目使用的是较旧的 Typescript 版本,无法正确推断类型。尝试将项目/工作区升级到更新的 TS 版本,看看它是否可以解决问题。此外,在发布 TS 问题时包含您的 tsconfig.json 可能会有所帮助,因为有时它可能归结为导致在 Playground 中未显示的意外问题。
-
ages是string[][],因为它确实扩展了ArrayUnion,因为它是一个数组。另外,在您的用例中,如果names预验证是string[],它应该是string[][]后验证吗? -
嗨@r3wt 感谢您的建议,我已经在上面包含配置的游乐场链接中重新创建了它。我已经更新了我的本地打字稿版本,它现在反映了操场上的问题。