【问题标题】:Typeguard return generic types for Intersections and UnionsTypeguard 返回交集和联合的泛型类型
【发布时间】:2022-06-10 23:17:32
【问题描述】:

我目前正在为我正在处理的项目编写一个复杂的自定义类型保护库,但我在理解函数签名为类型保护工作的方式时遇到了问题。

有一个通用的Is 函数采用以下形式:

type Is<A> = (a: unknown) => a is A

这使我可以编写表单的可组合类型保护

const isString: Is<string> = (u: unknown): u is string => typeof u === 'string'
const isNumber: Is<number> = (u: unknown): u is number => typeof u === 'number'

还有用于记录、结构、数组等的。比如数组一是

const isArray = <A>(isa: Is<A>) => (u: unknown): u is A[] => Array.isArray(u) && u.every(isa)

我有一个关于联合和交集类型的问题。

联合类型保护的签名是:

const isUnion<T extends Is<unknown>[]> = (...allTypeGuards: T): Is<T extends Array<Is<infer U>> ? U : never>

像这样称呼

const isStringOrNumber: Is<string | number> = isUnion(isString, isNumber)

对于交集是

function isIntersection<T, U extends Is<T>[]>(...args: U): Is<T>

例如:

const isFooAndBar: Is<{foo: string} & {bar: string}> = isIntersection(isStruct({foo: isString}),isStruct({bar: isString}))

我的问题是:为什么 isIntersection 和 isUnion 的签名是这样的?

对我来说,我会认为isIntersection 中的泛型isT 将是一个联合:如果您在打字稿中有一个数组['a', false, 1],那么该数组的类型是Array&lt;string | boolean | number&gt;,所以泛型T 将是 string, boolean, number,但 Is 函数的使用方式似乎有所不同。

同样使用 Union 函数,我不明白为什么需要使用 infer

请原谅我的英语:我试图解决这个问题已经筋疲力尽,我很乐意提供澄清。

【问题讨论】:

  • isUn​​ion 和 isIntersection 应该做什么?
  • 这会提出多个问题;你能只关注其中一个吗?在任何情况下,这似乎都不是minimal reproducible example(并且您应该修复拼写错误,就像您对isUnion 的定义中发生的任何事情一样)。 isIntersection() 调用签名不能开箱即用,并导致 Is&lt;unknown&gt;。我也不会像他们那样写isUnion()。修复它们看起来像this,虽然我可以解释 my 版本是如何工作的,但对于一些甚至没有演示的第三方代码,我不知道该说些什么。我们应该在这里做什么?
  • @jcalz 非常感谢您的帮助。我已编辑问题以提供示例,并将库移至公共仓库以防万一:github.com/ByteLondon/byteguards。我理解你的 isUnion 签名,你能解释一下 isIntersection 吗?

标签: typescript typescript-generics


猜你喜欢
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-24
  • 2017-12-18
相关资源
最近更新 更多