类型应该检测数组是否有重复项并在类型脚本中抛出错误?
type UniqueArray = [
// How to implement this?
]
const a:UniqueArray = [1, 2, 3] // success
const b:UniqueArray = [1, 2, 2] // error
PS:我目前正在使用JS删除重复的项目,但是,好奇的是,如果这个错误可以捕获使用 typescript 类型之前的手?
类型应该检测数组是否有重复项并在类型脚本中抛出错误?
type UniqueArray = [
// How to implement this?
]
const a:UniqueArray = [1, 2, 3] // success
const b:UniqueArray = [1, 2, 2] // error
PS:我目前正在使用JS删除重复的项目,但是,好奇的是,如果这个错误可以捕获使用 typescript 类型之前的手?
7条答案
按热度按时间fykwrbwg1#
在编译时,唯一可行的方法是数组是由文本组成的元组。例如,下面是一些运行时值相同但TypeScript类型不同的数组:
只有第一个会按照你的意愿运行......编译器会意识到
tupleOfLiterals
正好有3个元素,其中两个是相同的类型。在所有其他情况下,编译器都不知道发生了什么。所以如果你传递的数组是从其他函数或API等获得的,而这些数组的类型类似于number[]
,那么答案就是"不,你不能这么做"。如果你正在从一个使用你的代码作为库的开发者那里得到一个常量元组(可能通过
const
Assert),那么你有机会得到一些有用的东西,但是它很复杂,而且可能很脆弱。首先,我们提出了一个类似invalid type的东西,TypeScript没有这个东西。这个想法是一个不能赋值的类型(比如
never
),但是当编译器遇到它的时候,它会产生一个自定义的错误消息。下面的代码并不完美,但是如果你仔细看的话,它产生的错误消息可能是合理的:现在我们表示
UniqueArray
,它不能作为一个具体的类型(所以没有const a: UniqueArray = ...
)但是我们可以把它表示为一个泛型约束,传递给一个helper函数。不管怎样,这里有AsUniqueArray<A>
,它接受一个候选数组类型A
,如果它是唯一的,则返回A
。否则返回一个不同的数组,其中重复的位置有错误消息:它使用了大量的Map类型和条件类型,但是它实际上遍历了数组,并查看数组中是否有其他元素与当前元素匹配,如果匹配,则会显示一条错误消息。
现在来看看helper函数,另一个问题是,默认情况下,像
doSomething([1,2,3])
这样的函数会把[1,2,3]
当作number[]
,而不是[1,2,3]
的元组,因为没有simple way to deal with this,所以我们不得不使用一些奇怪的魔法(关于这个魔法的讨论,请参见链接):现在,
asUniqueArray()
只在运行时返回它的输入,但是在编译时它只接受它认为唯一的数组类型,并且如果有重复,它会在有问题的元素上放置错误:太好了,这就是你想要的,对吧?一开始的警告仍然有效,所以如果你最终得到的数组已经被加宽了(无论是非元组还是非文本),你会有不希望的行为:
无论如何,所有这些对你来说可能不值得,但是我想展示有一种,一种,也许,一种方法可以接近类型系统。希望能有所帮助;祝你好运!
Playground代码链接
f5emj3cl2#
是的!TypeScript 4.1有一种方法(在撰写本文时还处于beta版)。
如果同一个值出现多次,则会出现编译器错误。
Here's my article describing things in better detail.
在TypeScriptPlayground试用
j2qf4p5b3#
与approved answer非常相似,但是
InArray
被简化并内联。打字机游戏场
qc6wkl3g4#
又一个可读的(我希望)解决方案。
TSPlayground
yk9xbfzb5#
Typescript只执行编译时检查。Typescript无法检测到在运行时修改数组。另一方面,您可能希望使用Set类来防止插入重复项(但除非您检查返回值,否则不会引发错误)。但这不会引发编译时错误。
wxclj1h56#
适用于需要简单解决方案的用户的变通方案:
如果创建一个对象,重复的键将抛出如下错误:
但问题是,键是字符串,除了字符串,你不能在键中保存任何东西。
如果你不想拥有一个同时包含数字和字符串的唯一数组,这可能对你有用。然后,你可以像这样使用该对象:
,并将其用作数组。
2cmtqfgy7#
Typescript只引用类型,不引用值,而且,在运行时数组上它什么也不做。