TypeScript:来自字符串联合文字数组类型,不允许数组中存在任何冗余值
Posted
技术标签:
【中文标题】TypeScript:来自字符串联合文字数组类型,不允许数组中存在任何冗余值【英文标题】:TypeScript: from a string union literal array type, disallow any redundant values from existing in the array 【发布时间】:2021-01-22 08:32:36 【问题描述】:我正在使用很多文字字符串联合类型,以及它们的数组,用于一些与定义 SQL 表/视图及其所有列相关的代码。
请参阅下面的示例代码,其中我们有一个示例 user
SQL 表,其中包含以下列:id
、username
、email
、password
....
export type UserTableColumnName = 'id' | 'username' | 'email' | 'password';
export type ArrayOfUserTableColumns = UserTableColumnName[]; // This allows for redundant values, but I don't want it to allow them
function choose_some_user_table_columns(chosen_columns: ArrayOfUserTableColumns)
// function code not important
/**
* This is fine, no error should occur:
*/
choose_some_user_table_columns(['id', 'email']);
/**
* I want the code below to trigger a TypeScript typing error due to the 'email' element value being given twice:
*/
choose_some_user_table_columns(['id', 'email', 'email']);
有什么方法可以创建基于(或类似)UserTableColumnName[]
的类型 - 但是如果多次给出相同的值,TypeScript 会触发错误?例如email
在上面代码示例的最后一行被指定了两次。
我追求的是 TypeScript 解决方案(而不是运行时 JS 检查)。
理想情况下,如果我的编辑器(vscode,或任何支持 TypeScript 的编辑器)只建议数组中尚不存在的列名,那也很棒。目前,智能感知将自动建议每一列,无论它们是否已经在数组中。
【问题讨论】:
这能回答你的问题吗? Is there a way to define type for array with unique items in typescript? 只是一个想法:使用字典并使用列名作为键和布尔值作为值。 Typescript 没有抱怨,因为您正在实例化一个数组,其中每个成员都可以是列名之一。 【参考方案1】:您可以使用表示递归算法中每个步骤的映射类型来执行此操作,以生成所有允许的数组排列。 (TS 4.0+ 由于使用了可变元组,你可以在旧版本中做到这一点,但它会变得混乱)
type UniqueItems<T extends string, U extends string[] = []> = U |
[K in T]: UniqueItems<Exclude<T, K>, [...U, K]>
[T]
但是,请注意,这不能很好地扩展。在 T
联合中有 1 个项目,您将获得 2 个元组。有 2 个项目,5 个元组。有 N 个项目,2N + 1 个元组。 F*** 链接的答案在某些情况下会更好,但这将为其他情况提供显着更好的自动完成功能。 Playground link.
【讨论】:
感谢您的回答!您是否有机会根据我在 OP 中的现有类型添加一个使用UniqueItems<some-generics-here>
类型的示例?我尝试了type DisallowRedundant = UniqueItems<UserTableColumnName, ArrayOfUserTableColumns>;
和其他一些尝试,但似乎没有任何区别。我使用的是 TypeScript 4.0.3,所以不确定它是否足够新?
@LaVache 添加了游乐场链接
@Gerrit0 有没有办法将项目数量限制为n?
@roydukkey 你的意思是T
中的项目数吗?不,不是。在我看来,这首先是一个非常糟糕的模式。 Record<T, boolean>
在类型系统中处理起来要简单得多。
@Gerrit0 是的。我实际上通过重载参数找到了另一种方法。 github.com/roydukkey/typescript-storage/blob/…以上是关于TypeScript:来自字符串联合文字数组类型,不允许数组中存在任何冗余值的主要内容,如果未能解决你的问题,请参考以下文章