Limiting JSDoc/TypeScript type to a specific array element

Utilizing TypeScript with JSDoc poses a challenge as I aim to restrict a variable to one of the known values stored in an array.

I am aware that it can be achieved like so:

/** @type {'one'|'two'|'three'} */
let v = 'four';
// ==> Error, type 'four' is not assignable to type 'one'|'two'|'three'

In my scenario, the desired values are already defined in an array nearby. To prevent redundancy, I wish to reference them somehow, although I am uncertain if it's feasible. Something along these lines would be ideal:

const OPTIONS = ['one', 'two', 'three'];

/** @type {string<Options>} */
let v = 'four';
// ==> Desired -- Error, type 'four' is not assignable to type 'one'|'two'|'three'
// ==> but that doesn't actually work...

Is there any method to accomplish this?

Answer №1

Since August 28, 2021, you can achieve this by utilizing JSDoc inline @type {const} as shown below:

const OPTIONS = /** @type {const} */ (['one', 'two', 'three']);

/** @type {typeof OPTIONS[number]} */
let value = 'four'; 
//  ^ error: Type '"four"' is not assignable to type '"one" | "two" | "three" |

Answer №2

Modifying arrays at runtime may not be the best approach:

const CHOICES = ['red', 'blue', 'green'];
CHOICES[0] = 'YELLOW';

To ensure immutability, consider converting the array to a tuple:

const CHOICES = ['red', 'blue', 'green'];                
const CHOICES_TUPLE = ['red', 'blue', 'green'] as const;

Difference in inferred types:

// const CHOICES: string[]
// const CHOICES_TUPLE: readonly ["red", "blue", "green"]

Now you can enforce specific value types:

const OPTIONS_TUPLE = ['dog', 'cat', 'bird'] as const;
type PetsValue = typeof OPTIONS_TUPLE[number];
const y: PetsValue = 'fish'; 
//TS2322: Type '"fish"' is not assignable to type '"dog" | "cat" | "bird"'.

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

Understanding the Functions of Angular Providers and Implementing Them

Just starting out with Angular and following a tutorial from this video. I decided to experiment by adding providers :[EmployeeService] to both employee-list.component.ts and empployee.component.ts within the @component section. However, this led to an err ...

Error in NodeJS when trying to run ESM: "ReferenceError: exports is not defined

Having a tough time with this task. I'm attempting to execute ESM scripts on Node 14 (AWS Lambda) I am working on running this piece of code to convert 3D objects to THREE JSON. This involves using the command node -r esm fbx2three.js model.fbx. I ...

What is the process for generating an injected and a const object instance?

How can an instance of class A obtain a dependency on an instance of class O, while remaining a singleton for others? @injectable() class O{} // A must be single instance! @injectable() class A{ constructor(o: O){ console.log( 'is A inst ...

What is the correct method for typing sagas?

After diligently following the official redux documentation for integrating with TypeScript, which can be found at https://redux.js.org/recipes/usage-with-typescript, I successfully typed actions, reducers, react components, and more. However, my progress ...

Customize YouTube iframe styles in Angular 4+ with TypeScript

Has anyone been successful in overriding the style of an embedded YouTube iframe using Angular 4+ with TypeScript? I've attempted to override a CSS class of the embed iframe, but have not had any luck. Here is the URL to YouTube's stylesheet: ...

What is the process for exporting the reducer function and integrating it into the storeModule.forRoot within an Angular application?

Recently, I started delving into ngrx and decided to educate myself by going through the official documentation on their website ngrx.io. During this exploration, I came across a puzzling piece of code in one of their reducers. The file in question is cou ...

Unusual conduct exhibited by a 16th version Angular module?

I've created a unique component using Angular 16. It's responsible for displaying a red div with a message inside. import { ChangeDetectionStrategy, Component, Input, OnInit, } from "@angular/core"; import { MaintenanceMessage } ...

Tips on updating the content of an HTML element dynamically when it is already being populated using *ngFor

I have created an HTML component that utilizes *ngFor to dynamically generate HTML elements. This results in a total of 3 tags being generated when the code is run. I have included data such as subject in the component file which updates dynamically, how ...

Tips on obtaining checkbox values other than "true"

Having trouble retrieving the values of selected checkboxes instead of displaying "Custom Category"? I've attempted to access the values and attributes with no success. I'm aiming to display the values of the selected checkbox. app.component.ht ...

Utilizing MongoDB query for geoLocation with maxDistance parameter

Customer location: customerCoordinates: [83,24] stores: { id:1, location: {coordinates:[85,44]...} maxRadiusDelivery: 2000 //meters }, { id:2, location: {coordinates:[82,34]...} maxRadiusDelivery: 100 //meters } Query: db.wh.find({ 'locati ...

Updating the navigation bar in Node/Angular 2 and displaying the sidebar once the user has logged in

I am facing a challenge with my first project/application built using Angular 2, particularly related to the login functionality. Here is what I expect from the application: Expectations: When I load the login component for the first time, the navbar ...

Tips for creating a typescript typeguard function for function types

export const isFunction = (obj: unknown): obj is Function => obj instanceof Function; export const isString = (obj: unknown): obj is string => Object.prototype.toString.call(obj) === "[object String]"; I need to create an isFunction method ...

Utilizing a directive in contexts beyond a component

I have developed a popover module that consists of two components and three directives. However, I am encountering an issue where I am unable to utilize the directives outside of the main component. Whenever I try to do so, I face an editor error stating: ...

Using Angular filter pipe to customize markers in Leaflet maps

I am currently working on a select element called district, which lists all the districts in the city. My objective is to apply a filter that will dynamically display only the leaflet markers corresponding to the selected district on the map. Any suggesti ...

Error: Issue determining the type of variable. Unable to eliminate type 'any'

I am trying to load some widgets from a template object (possibly JSON in the future). Here's an example: type RectangleTemplate = { name: 'Rectangle'; props: { width: number; height: number; } }; type ButtonTemplate = { nam ...

Traversing an array of objects in TypeScript and appending to a separate array if not already present

I have been given an array containing objects in the following format: export interface Part { workOrder?: string; task?: string; partNumber?: string; qty?: number; image?: string; name?: string; } My goal is to loop through each object in th ...

The database did not respond, causing the API to resolve without sending a response for the specified endpoint (/api/dates). This could potentially lead to requests becoming stalled in Next

I have been attempting to retrieve a list of dates from my database in a straightforward manner, but unfortunately, I am not receiving any response (even after trying to log the response data to the console). The only feedback I seem to be getting when sel ...

What is the best way to execute a function that retrieves data from a MySQL query and then sends it back as a result in Express.js?

How can I refactor my code to efficiently call a function that returns the result of a MySQL query and send it back in an Express.js response? I am attempting to streamline my SQL queries by exporting them into individual functions to eliminate duplicatio ...

Balancing website speed with capturing product impression

I've been tasked with capturing impressions of all the products visible in the viewport on a website that features thousands of products. To achieve this, I implemented a directory and utilized the IntersectionObserver, which was referenced within the ...

How can I receive live notifications for a document as soon as it is created?

My Angular app is connected to Cloud Firestore, and I've created a function in a service to retrieve a user's rating from the 'ratings' collection. Each rating is stored in this collection with the document ID being a combination of the ...