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 表,其中包含以下列:idusernameemailpassword....

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&lt;some-generics-here&gt; 类型的示例?我尝试了type DisallowRedundant = UniqueItems&lt;UserTableColumnName, ArrayOfUserTableColumns&gt;; 和其他一些尝试,但似乎没有任何区别。我使用的是 TypeScript 4.0.3,所以不确定它是否足够新? @LaVache 添加了游乐场链接 @Gerrit0 有没有办法将项目数量限制为n @roydukkey 你的意思是T 中的项目数吗?不,不是。在我看来,这首先是一个非常糟糕的模式。 Record&lt;T, boolean&gt; 在类型系统中处理起来要简单得多。 @Gerrit0 是的。我实际上通过重载参数找到了另一种方法。 github.com/roydukkey/typescript-storage/blob/…

以上是关于TypeScript:来自字符串联合文字数组类型,不允许数组中存在任何冗余值的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript中的类型化数组到文字类型

如何从 Typescript 中的常量定义字符串文字联合类型

TypeScript:从字符串数组定义联合类型

TypeScript 基础类型

TypeScript:推断嵌套联合类型的类型

TypeScript(14): 联合类型