Design a TypeScript interface inspired by a set static array

I am working with an array of predefined strings and I need to create an interface based on them. To illustrate, here is an example of pseudo-interfaces:

const options = ["option1", "option2", "option3"];

interface Selection {
    choice: keyof options;
}

In my JavaScript code, I have to use the options in the same order as listed in the array. I am looking for a way to define this relationship in the interface without duplicating the values between the array and the interface. Is there a way to achieve this?

Answer №1

Understanding this concept can be challenging, as the issue arises when the data type 'types' is converted to 'string[]', losing valuable information about the specific strings in the array and their order.

If your focus is solely on the individual strings and not their sequence, a workaround exists where a helper function can manipulate 'types' into a more restrictive type (refer to this article for details on avoiding widening):

const narrowArray = <K extends string>(...arr: K[]) => arr;

Implement it like so:

const types = narrowArray("error", "warning", "success");

Now 'types' will be identified as

Array<"error"|"warning"|"success">
. If you intend for 'Modal['types']' to reference one of these strings (unclear from your post... 'keyof' won't achieve this), follow this approach:

interface Modal {
    type: (typeof types)[number];  // "error" | "warning" | "success"
}

These steps should meet your requirements.


Another noteworthy element is that TypeScript version 3.0 introduces a feature to infer tuple types, enabling the preservation of the ordering within 'types'. It functions as illustrated below:

// only operational in TS3.0 and later
const narrowTuple = <K extends string[]>(...arr: K) => arr;
const types = narrowTuple("error", "warning", "success");
// 'types' now signifies type ["error", "warning", "success"]

'types' is now specified as the triple ["error", "warning", "success"], providing TypeScript with knowledge during compilation that, for instance, types[1] specifically corresponds to "warning". The ordering information need not be retained for the definition of 'Modal['type']' as mentioned above, unless there's a different intent for 'Modal['type']'.


Hopefully, this explanation proves beneficial. Best of luck!

Answer №2

Unfortunately, the creation of a dynamic interface at runtime is not supported. This approach would go against the principle of static typing.

One possible workaround is to define an enum and use it to specify types like so:

export enum StatusCodes {
  error = 'error',
  success = 'success',
  warning = 'warning'
}
const types: Array<StatusCodes> = [StatusCodes.error, StatusCodes.success, StatusCodes.warning]

interface Modal {
  type: StatusCodes
}

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

Exploring FileReader in conjunction with React and Typescript

I am facing an issue while trying to upload a JSON file using an input element of type file. When I attempt to use the onload method on FileReader in TypeScript, I receive an error message saying "Cannot invoke an object which is possibly 'null'. ...

Is there a way to trigger jQuery animations even when the browser window is not in focus?

Hi there, I am currently working on developing an ajax-based multiplayer game that connects to a server for updates. The game has various game states and requires the GUI to be animated accordingly. However, I have encountered a problem where jquery anima ...

Modifying the Vue.js Vue3-slider component for custom color schemes

Currently, I am using the vue-slider component and would like to customize the color of the slider itself. The specific class that needs to be styled is "vue-slider-dot-tooltip-inner". Below is a screenshot displaying the original CSS styling for vue-slid ...

What is the best method for retrieving the current value of an RxJS Subject or Observable?

I am dealing with an Angular 2 service: import {Storage} from './storage'; import {Injectable} from 'angular2/core'; import {Subject} from 'rxjs/Subject'; @Injectable() export class SessionStorage extends Storage { priv ...

A guide on implementing multiple ternary operators in a Vue.js template

Is it possible for a template to return three different values instead of just two, based on the data? I am familiar with using two conditions, but is there a way to use more than two without getting a syntax error? <option {{ change === 1 ? &apos ...

Form submissions are not saving checkbox answers

As a beginner, I'm struggling to save the checkbox answers on the page after submission. The code below is quite lengthy (checkboxes start at 314). I have a feeling that I might be missing a piece of code, but I just can't seem to pinpoint what i ...

Can you explain the concept of System.register in a JavaScript file?

Can you explain the purpose of System.register in a JS file when utilizing directives in Angular 2? ...

The TypeScript compiler is unable to locate the identifier 'Symbol' during compilation

Upon attempting to compile a ts file, I encountered the following error: node_modules/@types/node/util.d.ts(121,88): error TS2304: Cannot find name 'Symbol'. After some research, I found that this issue could be related to incorrect target or l ...

Resolving the non-null assertion error in TypeScript and React: A step-by-step guide

My code snippet is as follows: type ItemProps = { status?: string; } <Items status={status!} /> // encountering an error with a warning about forbidden non-null assertion // @typescript-eslint/no-non- ...

What is the method for retrieving a PHP JSON variable value and displaying it in HTML?

Using the graph API, I managed to retrieve my Facebook friend list and received a JSON array as a response. The value of that array is stored in a variable like this: $json_output=($result['summary']['total_count']); echo "$json ...

Guide to transmitting and managing a JSON document utilizing JavaScript

When working on the server side, I receive a simple JSON file via REST that contains various IDs. Here is an example: [ { "_id": "5825a49dasdasdasd8417c1b6d5", } "_id": "dfsdfsdf4960932218417c1b6d5", } "_id": "23434344960932218417c1b6d5", },] To handle t ...

The chosen selection automatically deactivates the checkbox with a matching value

I am looking for a solution where selecting an option will automatically disable the checkbox with the corresponding value. The existing methods I have come across are static and rely on hardcoded values. <select name="pickOne" id="pickOn ...

Tips on how to retrieve the value of the second td in an HTML table when clicking on the first td utilizing jQuery

There is a specific requirement I have where I must retrieve the value of the second td in an HTML table when clicking on the first column. To accomplish this task, I am utilizing jQuery. $('.tbody').on('click','tr td:nth-child(1) ...

The useRoutes function is returning null despite the correct pathname being provided

Check out my React code snippet! I've got the Component nestled within a micro-frontend application, which is then brought into the main app using module federation. // embedded in my microfrontend. const path = '/another-component-path'; f ...

Using an external script to modify or call a Vue.js method

My Vue app is constructed using Webpack and includes a few basic computed properties, such as calculating the sum amount from input values. However, I now require the capability to replace the summation function with one stored in a separate file that is n ...

What are the ways to change a PDF file or web address into a DOCX document using NodeJS?

I've been doing some research on converting URLs to DOCx or PDF to DOCx in NodeJS, but I haven't found a proper solution yet. I tried reaching out to PhantomJS, but it only converts URLs to PDF. Do you have any idea if PhantomJS can convert to D ...

The Firebase 'not-in' operator is malfunctioning

Within my database, there is a document located at: https://i.stack.imgur.com/OTZpd.png I am attempting to query the number of messages documents where the user's ID does not appear in the "read_by" array. This is the code I am currently using: const ...

The Bootstrap navbar stubbornly refuses to hide after being clicked on

Is there a way to adjust the data-offset-top for mobile view? Additionally, I am having trouble hiding the menu when clicking on a link. I have tried some code from stackoverflow without success. Can someone please assist with this issue: <nav class= ...

Transforming a React Class Component into a React Functional Component

After struggling for a day with multiple failed attempts, I have been unsuccessful in converting a React Class Component. The original class component code is as follows: class NeonCursor extends React.Component { constructor(props) { super(props); ...

The presence of 'eventually' in the Chai Mocha test Promise Property is undefined

I'm having trouble with using Chai Promise test in a Docker environment. Here is a simple function: let funcPromise = (n) => { return new Promise((resolve, reject) =>{ if(n=="a") { resolve("success"); ...