Ensure that a TypeScript string union literal array type does not contain any duplicate values

In my code related to defining SQL tables/views and their columns, I am utilizing literal string union types and arrays.

Take a look at the sample code below featuring a mock user SQL table with columns: 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']);

Is there any way to create a type similar to UserTableColumnName[] that will prompt a TypeScript error if a value is repeated? For example, triggering an error when 'email' is specified twice in the last line of the code snippet above.

I'm seeking a TypeScript solution over a runtime JS check, and it would be ideal if my editor (such as vscode) only suggests column names not already present in the array, improving intellisense functionality.

Answer №1

To tackle this task, you can utilize a mapped type that represents each stage in a recursive algorithm designed to generate all valid array permutations. (Note: TS 4.0+ is required due to the usage of variadic tuples. While possible with older versions, it may lead to complexity)

type UniqueItems<T extends string, U extends string[] = []> = U | {
  [K in T]: UniqueItems<Exclude<T, K>, [...U, K]>
}[T]

It's essential to note that this approach may not be efficient for large datasets. For instance, with one item in the T union, you will obtain two tuples. With two items, it grows to five tuples. And when there are 'N' items, you'll end up with 2N + 1 tuples. The solution shared by Fabian might be more suitable in certain scenarios, but this method excels at providing significantly enhanced autocomplete functionality in others. Take a look here on the playground.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error Detected: An unhandled error occurred, triggering a promise rejection: TypeError: The super expression must be either null or a function in Angular version 6

Upon deploying the application on AWS Elastic Beanstalk, an error has surfaced. While the build and deployment processes were successful, one module is giving a Super Expression error. The other modules are functioning correctly, and everything works fine ...

Creating an Array of UIBezierPaths in Swift

Creating a 10x10 grid of squares (UIBezierPaths) in Objective-C was a breeze - just slap a "[10]" on the declaration and you're all set. But Swift arrays are a whole new ball game for me. Despite searching through numerous posts, I am still struggling ...

What could be causing the class methods in my NestJS DI to be stored as undefined values in a map?

I came up with an EventService to manage custom events that are added through a special decorator. Everything appears to be functioning correctly, but the issue arises when attempting to access the methods within the stored event class as they return undef ...

PHP: Parse a JSON file containing an array with multiple objects, then separate each object individually

My file contains data that looks like this: [{"color":1,"blocks":[[{"id":64}]]},{"color":1,"blocks":[[{"id":64},{"id":64}],[{"id":1}]]},{"color":2,"blocks":[[{"id":64},{"id":64}],[{"id":1}]]}] There are 3 objects in the file, each with 'color' ...

Creating pagination in Vue using an array of objects

I'm new to Vue and arrays and I need help paginating my json array so that only 10 items are displayed per page. Currently, all the items in the array are being shown in the <tr> body. I've tried different methods without success. Can someo ...

Is there a way to retrieve the object property within the subscribe function in order to display the HTML content?

Is there a way for me to update the HTML using the properties obtained within .subscribe? I am aware that .subscribe is asynchronous and therefore returns an undefined value initially, but how can I ensure it waits until the value is resolved? Currently, I ...

Tips for securely encrypting passwords before adding them to a database:

While working with Nest.Js and TypeORM, I encountered an issue where I wanted to hash my password before saving it to the database. I initially attempted to use the @BeforeInsert() event decorator but ran into a roadblock. After some investigation, I disc ...

Exploring the concept of object inheritance in Angular 5 with Typescript

I'm facing a challenge related to inheritance while building my initial angular 5 application. The error message I encounter is: Property 'message' does not exist on type 'CouponEvent', as reported by the angular-cli. export class ...

Ensure that Vuex state can only be accessed through a getter function

Our goal is to have a variable in our Vuex store that can only be accessed through the getter function. To do this, we must ensure that the variable is protected from external access outside of the store. What options are available to us? ...

Comparing Array Elements within a Function

As I embark on my C class, a common yet perplexing question arises regarding the implementation of comparing elements within two variable-length arrays in a separate function. The task at hand is to identify and extract any shared elements found in both ar ...

Lazy loading in Angular - struggling to verify its functionality

A module for lazy loading was created by me. This particular module is called SettingsRoutingModule- const routes: Routes = [ { path: '', component: SettingsStandaloneComponent, children: [ ...

What is the best way to link together a varying amount of observables?

Being new to Angular and Observables, I am looking for a way to efficiently chain the call of a service multiple times. Is there a straightforward method using Observables that can achieve this in a more generic manner than traditional methods? (similar ...

What is the best approach to writing a Java program that identifies the presence of 0's and 1's?

My task is to take 10 values from the keyboard and determine whether any of the inputs contain the numbers 0 or 1. If so, I need to identify the position of these numbers in the array. example Input = 9 15 91 1 0 22 31 67 88 33 output = 4 found number 1 ...

Top approach for retrieving values from a multidimensional array in PHP

I want to extract all the values from a multidimensional array like this: $post = array( 'k'=>'kk', 'l'=>'ll', 'n'=>array( 't'=>'tt', 'n'=&g ...

Combining Two JSON Arrays Featuring Unique Keys

I have two JSON arrays with slightly different keys. The first JSON array contains the keys id, name, and title. The second JSON array includes id, title, forename, name, and company. I am wondering if it's possible to merge these two arrays so th ...

Utilizing PrimeNG menu items to bind commands to a base class function

I'm struggling to connect a parent class function with my Angular 2 PrimeNG menu options. HTML <p-menu #menu popup="popup" [model]="exportItems"></p-menu> <button type="button" class="fa fa-download" title="Export As" (click)="menu.to ...

Leverage TypeScript to access custom component properties and URL parameters from react-router-dom

In my react-router-dom setup, I have a route structured like this: <Route path="/result/:result" component={ResultsView} audio={audio} speechRecognition={speechRecognition} /> Furthermore, I have a component with specified props as follows ...

Arrays.sort causing performance problems in Java

After successfully solving one algorithmic problem, I encountered a strange issue while working on my code in Java 8/17, Intel 11th gen processor. The main focus is on the `solve` function where a simple solution is implemented by calling the `findDistFor ...

iterating over a array of characters in c++

#include <iostream> #include <string> using namespace std; bool isValidID(char [], int); int main() { const int length = 8; char ID[length]; cout << "Please enter an ID in the format "; cout << "ABC1234\n"; ...

Typescript for controlling the pause and resume functionality of a Bootstrap 4 carousel

I am creating a web application with Angular 4 and Bootstrap 4 beta. I need to pause the carousel when a user clicks on an image to display a modal, and then resume the carousel once the modal is closed. However, I have encountered an issue where changing ...