Can we guarantee the uniqueness of a function parameter value during compilation?

I have a set of static identifiers that I want to use to tag function calls. Instead of simply passing the identifiers as arguments, I would like to ensure that each identifier is unique and throws an error if the same identifier is passed more than once:

type Id = 'id-1' | 'id-2';

function foo(id : Id) {
  console.log(`my id: ${id}`);
}

foo('id-1');
foo('id-2');

Is there a way to create a magic type in TypeScript that enforces uniqueness for the identifiers passed to the function?

type MagicId = /* some magic type to achieve uniqueness */;

function foo(id : MagicId) {
  console.log(`my id: ${id}`);
}

foo('id-1');
foo('id-1'); // should throw a type error

Answer №1

If you want to achieve a certain behavior, you can use objects in the following way:

type Id = 'id-1' | 'id-2';

function _foo(id: Id) {
  console.log(`My id: ${id}`)
}

function foo<T extends Id>(id : T) {
  _foo(id);
  return {
    foo(id: Exclude<Id, T>) {
      _foo(id);
    }
  }
}

foo('id-1').foo('id-2'); // this is okay

foo('id-1').foo('id-1'); // this will result in an error

The outer foo function can accept both "id-1" and "id-2", while the inner can't due to type exclusion.

This approach works best for consecutive calls, as opposed to sporadic usage of the functions.

You can try out the code on the playground.

An enhanced version could be the following:

type Builder<T> = {
  foo<I extends T>(id: I): Builder<Exclude<T, I>>;
};

const builder = {
  foo<T extends Id>(id: T): Builder<Exclude<Id, T>> {
    console.log(`My id ${id}`);
    return this;
  },
};

builder.foo("id-1").foo("id-2");

This method recursively removes the types that have already been used:

builder
  .foo("id-1") // acceptable, allows usage of "id-2"
  .foo("id-2") // all values have been used, next one defaults to `never`
  .foo("id-1") // error, as "id-1" cannot be assigned to `never`

Check out the playground for more details.

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 in StoryBook addon-docs: "No props discovered for this particular component" when utilizing TypeScript

Encountering an issue with a TypeScript and StoryBook project: The table displaying component properties is not generated nor visible in the StoryBook "Docs" tab on a TypeScript-based project setup. Instead of the expected table, a message saying "No pro ...

What is the process of changing a number to the double data type in JavaScript or TypeScript?

Within a single input field, users can enter various numbers such as 12, 12.1, 12.30, and 12.34. The challenge is to pass this value in a service call where only the value can be sent as a number but with two decimal points. let a = input //a will be a ty ...

Locating a class variable using a string chosen from a DropDown menu

In my Tv class, I have several string variables. One requirement is for the user to select an option from a DropDown list and input a value. This entered value should then be stored in the Tv class under a variable with a similar name to the selected optio ...

Adjusting the transparency of TabBadge in Ionic 2

I am currently working on a project that involves tabs, and I'm looking to update the style of the badge when the value is 0. Unfortunately, I am unsure how to dynamically change the style of my tabs or adjust the opacity of the badge in the style. M ...

Issues with Angular ng-bootstrap tabset component not functioning as expected

{ "name": "ModalWindow", "version": "1.0.0", "repository": { "type": "git", "url": "" }, "scripts": { "build": "webpack --mode production", "start": "webpack-dev-server --mode development --open" }, "license": "MIT", "depend ...

Tips for accessing the value from a subscription within a function in Ionic 3

I am working on a function that retrieves a JSON file from a specific URL. The issue I am facing is that I am trying to access a random object from this data within the file, stored in this.data. However, when I attempt to console.log(this.data) outside of ...

Angular date selection with a range of plus two days, factoring in the exclusion of weekends

I am currently using a mat date picker range with specific logic. The minimum date that a user can select on the calendar is set to + 2 days. For example, if today's date is July 20, 2022, the minimum selectable date would be July 22, 2022. However, ...

Error: Angular does not recognize session storage reference

While my project is up and running, I have encountered an error in the terminal. let obj = { doc_id: sessionStorage.getItem('doc_id'), batch_no: sessionStorage.getItem('batch_no') } I attempted to make adjustments by a ...

Attempting to transfer information between components via a shared service

Currently, I am utilizing a service to transfer data between components. The code snippet for my component is as follows: constructor(private psService: ProjectShipmentService, private pdComp: ProjectDetailsComponent) { } ngOnInit() { this.psSe ...

What is the best way to trigger an API call every 10 seconds in Angular 11 based on the status response?

I am in need of a solution to continuously call the API every 10 seconds until a success status is achieved. Once the success status is reached, the API calls should pause for 10 seconds before resuming. Below is the code I am currently using to make the A ...

Suddenly encountered issue when working with TypeScript Interfaces while integrating Quicktype 'allOf'

Our transition from using JSON Type Definition to JSON Schema includes the utilization of Quicktype to convert JSON Schemas into TypeScript Types. While Quicktype has been effective in most cases, it seems to struggle with converting Discriminators and mor ...

Retrieve the values of a dynamic JSON object and convert them into a comma-separated string using Typescript

I recently encountered a dynamic JSON object: { "SMSPhone": [ "SMS Phone Number is not valid" ], "VoicePhone": [ "Voice Phone Number is not valid" ] } My goal is to extract the va ...

What is the best way to specify types for a collection of objects that all inherit from a common class?

I am new to typescript and may be asking a beginner question. In my scenario, I have an array containing objects that all extend the same class. Here is an example: class Body{ // implementation } class Rectangle extends Body{ // implementation } class ...

The issue of circular dependencies in TypeScript arises specifically within the Record type rather than in an ordinary object type

Can you explain the difference between two types, where one throws a TS error and the other does not? type ScopeItem = | string | { all: string; team: string; }; type ScopesTree = Record<string, ScopeItem | Record& ...

nodemon failing to automatically refresh files in typescript projects

I am currently developing an app using NodeJs, express, typescript, and nodemon. However, I am encountering an issue where the page does not refresh when I make changes to the ts files. Is there a way for me to automatically compile the ts files to js an ...

Retrieving an array of objects from an API and attempting to store it using useState, but only receiving an empty

I have been working on fetching data from an API, storing it in Redux store initially, and then attempting to retrieve it using useSlector to finally save it in local state. Despite getting the data when I console.log it, I am unable to successfully store ...

Modifying the menu with Angular 4 using the loggedInMethod

Struggling to find a solution to this issue, I've spent hours searching online without success. The challenge at hand involves updating the menu item in my navigation bar template to display either "login" or "logout" based on the user's current ...

Having trouble accessing the useState hook in React context value with TypeScript

export const TeamMemberContext = createContext<TeamMembersList[] | null>(null); export const TeamMemberProvider = ({ children }) => { const [teamMemberList, setTeamMemberList] = useState<TeamMembersList[] | null>(null); useEffect(( ...

Definition of a class in Typescript when used as a property of an object

Currently working on a brief .d.ts for this library, but encountered an issue with the following: class Issuer { constructor(metadata) { // ... const self = this; Object.defineProperty(this, 'Client', { va ...

What steps should I take to resolve the 'invalid mime type' issue while transmitting an image as a binary string to Stability AI via Express?

Currently, I am facing an issue while attempting to utilize the image-to-image API provided by stabilityAI. The task at hand involves sending an image as a binary string through my express server to the stability AI API. However, when I make the POST reque ...