假设我有3种这样的对象
type mainType = {type:'main', name?:string}
type contentType = {type:'content', text?:string}
type buttonType = {type:'button', name:string}
我想输入一个数组,每个类型至少有一个。假设它会像这样
[
{type:'main'},
{type:'main', name:'Some name'},
{type:'content', text:"Some text"},
{type:'button', name:'Add'},
{type:'button', name:'Submit'}
]
怎么样才能把它打出来?
联合类型不起作用,因为它不会检查该类型是否丢失。
最接近的解决方案是使用扩展操作符?,但是如果我不知道顺序的话就不行了。
这是我的第一个问题,希望它有意义。
2条答案
按热度按时间4ktjp1zp1#
这是在或过去的边缘,我认为在TypeScript中可以合理地表达。
首先,TypeScript中没有特定的类型
type GoodArray = ⋯
来表示您正在谈论的内容。TypeScript具有元组类型,可以表示具有特定数字索引处的特定类型元素的数组。但是你不关心哪个索引保存你的类型的元素,只要它们至少出现一次。这意味着您的需求需要被编写为所有元组类型的无限联合,这些元组类型以您想要的方式工作……比如
TypeScript不支持无限联合。你可以选择一些相对较小的最大数组长度来支持,这是可行的,因为你只是有一个巨大的联合,而不是一个无限的。这也不太可行。
您可以创建一个generic类型而不是一个特定的类型,它的作用就像对类型的约束,因此
T extends GoodArray<T>
当且仅当T
有效。然后你还必须创建一个通用的辅助函数
goodArray()
,它将接受一个参数并验证其类型。因此,您可以编写const arr = goodArray([⋯]);
,而不是编写const arr: GoodArray<⋯> = [⋯];
并手动写出T
类型参数不幸的是,要做到这一点也不是很简单。泛型类型需要找出缺少了哪些元素类型(如果有的话),然后在某个地方需要它们。一种方法是使用可变元组类型生成递归条件类型来解析输入。就像这样:
我不知道这是否值得重点是遍历
T
,跟踪使用了哪些类型,然后在最后返回数组,或者修改最后一个或两个元素以需要缺少的类型。所以我们会看到:然后是helper函数;理想情况下,我们应该写
<T extends GoodArray<T>>(arr: T) => arr
,但这是一个非法的循环约束。所以我们需要用推理和变量元组来玩游戏…那么这个:我们可以测试它,它可以工作:
但这很复杂
最后,所有这些都只允许您验证开发人员编写的某些特定数组文字。编译器不“理解”约束。如果你有一个接受
GoodArray
或GoodArray<T>
的函数,它不会真正“知道”,例如,ButtonType
肯定存在:find()
array method返回一个可能的undefined
值。因此,您会发现自己要么需要进行额外的运行时检查,要么需要使用类型Assert来避免此类错误。总之,这一切意味着:我不会真的尝试依赖类型系统来做这类事情,或者至少我会非常清楚所涉及的限制。
Playground链接到代码
irlmq6kh2#
我不知道这对你来说是否是一个解决方案,但你可以像这样输入你的数组:
但这要求数组的前三个元素的顺序正确。