Tips for obtaining intellisense for the value in a readonly string array property within an object without relying on generics

Keeping it brief and to the point. What is the reason behind this?

type ReadonlyStringArray = readonly string[]

type TEnumGeneric<EnumIsh extends ReadonlyStringArray> = {
    type: "enum",
    values: EnumIsh
}

type TEnumImplied = {
    type: "enum",
    values: ReadonlyStringArray
}
type EVal<T extends TEnumImplied> = {
    value: T["values"][number]
}

It supports the following:

const somearr = ["foo", "baz", "bar"] as const
const x: TEnumGeneric<typeof somearr> = {
    type: "enum",
    values: somearr
}
const z: EVal<typeof x> = {
    value: "bar"
}

But what about this?

const y: TEnumImplied = {
    type: "enum",
    values: ["foo", "bar", "baz"] as const
} as const
const z: EVal<typeof y> = {
    value: "" //???
}

My assumption is that it would only allow one of the values in y.values since the values for TEnumImplied are read-only...?

Answer №1

When you declare a variable with a specific type like TEnumImplied, the compiler only recognizes that specified type. Even if you assign a const-asserted value to it, the variable's type remains unchanged (unlike variables of union types which can have their type narrowed through assignments).

For instance, if we have:

const y: TEnumImplied = {
  type: "enum",
  values: ["foo", "bar", "baz"] as const
} as const

The type of y will simply be TEnumImplied and not influenced by "foo", "bar", or "baz":

y
//^? const y: TEnumImplied

Hence, EVal<typeof y> equates to { value: string; } because

TEnumImplied["values"][number]
is string:

type E = EVal<typeof y>
//   ^? type E = { value: string; }

If this behavior is not desirable, it's advisable not to specify the type for y.


Perhaps your intention is to merely verify that the type of y is assignable to TEnumImplied without changing its actual type. In such cases, you can utilize the satisfies operator. Instead of writing const vbl: Type = expr;, you can use const vbl = expr satisfies Type. Both approaches will raise an error if expr isn't of type

Type</code, but while the first method widens <code>vbl
to Type, the latter infers the type of vbl based on expr (with Type serving as a contextual type for inference).

Thus, updating the previous example to:

const y = {
  type: "enum",
  values: ["foo", "bar", "baz"] as const
} as const satisfies TEnumImplied;

Will give you the expected type for y:

y
//^? const y: { 
//     readonly type: "enum"; 
//     readonly values: readonly ["foo", "bar", "baz"]; 
//   }

Consequently, the resulting type for EVal<typeof y> will also be as anticipated:

type E = EVal<typeof y>
//   ^? type E =  { value: "foo" | "bar" | "baz"; }

(Playground link to original code)

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

Building a versatile memoization function in JavaScript to cater to the needs of various users

There is a function in my code that calculates bounds: function Canvas() { this.resize = (e) => { this.width = e.width; this.height = e.height; } this.responsiveBounds = (f) => { let cached; return () => { if (!cache ...

Tips for choosing multiple files with the Ctrl key in a list item element:

We have decided to create our own browsing functionality due to the limitations of the existing HTML browse feature. While using the HTML browse, we can only select multiple files by pressing the Ctrl key, and we want to replicate this feature in our custo ...

The problem of a circular reference arose when attempting to pass the model using the JSON.stringify method

I am looking to replace all fields with null values to prevent the model from proceeding further. However, when I attempt to create a replacer function and pass the model, I am encountering a circular reference issue. Is there a more effective way to accom ...

Exploring the possibilities of combining DOM and Express in web development

app.post('/result.html',function(req,res){ var num1 = req.body.Num1 ; var num2 = req.body.Num2 ; var operator = req.body.Operator ; var result =0 ; switch (operator) { case '+': result = Number(num1)+Number(num2) ; ...

Tips for sending arguments to translations

I am currently implementing vuejs 3 using TS. I have set up my translation files in TypeScript as shown below: index.ts: export default { 'example': 'example', } To use the translations, I simply do: {{ $t('example') }} N ...

Implementing the Jssor slider

Recently, I've been using the jssor slider on multiple pages without any issues. However, I am now facing some challenges. Ideally, I want the slider to be hidden initially and then displayed with another script. While I have managed to achieve this v ...

Tips for sending a Django queryset as an AJAX HttpResponse

Currently, I am faced with the challenge of fetching a Django queryset and storing it in a JavaScript variable using Ajax. I have attempted to employ the following code snippet for this purpose; however, I keep encountering the issue of "Queryset is not J ...

Angular 5's data display glitch

Whenever I scroll down a page with a large amount of data, there is a delay in rendering the data into HTML which results in a white screen for a few seconds. Is there a solution to fix this issue? Link to issue I am experiencing HTML binding code snippe ...

A type error was thrown: $.ajax function does not exist within another function

I encountered a persistent ajax error on the website. Error : Uncaught TypeError: $.ajax is not a function at Hei Here is my code for reference: Can anyone pinpoint where I may be going wrong? The suggested solutions from other sources have not resol ...

Exploring Angular 5's *ngFor directive with an array of objects

Here is the data I am working with: Initial set of data: var input = [ {ru: "R201", area: "211", unit: "211"}, {ru: "R201", area: "212", unit: "NONE"}, {ru: "R201", area: "HCC", unit: "NONE"}]; Desired result data: var result = [ {area: ...

Is it possible to modify the authenticated user ID right before its creation in Firebase, especially when the user is being created via the Facebook provider?

As we transition our MongoDB database to Firebase with Firestore, we are facing the challenge of integrating Firebase authentication for our users. Currently, we store user data in Firestore and want to utilize Firebase authentication for user logins. Each ...

Show the quantity of chosen selections utilizing ng-select

I have implemented the ng-select component for users to select multiple options from a list. My goal is to have the selected option displayed normally when only 1 option is chosen. However, if 2 or more options are selected, I want a custom template to sh ...

Tips for implementing pagination in the frontend (specifically Angular) with a pre-defined limit from the backend (NodeJS, TypeORM)

Exploring Angular and NodeJS for the first time, I am eager to implement pagination in my frontend listing. While I have successfully limited entries in my backend method, I am facing challenges in integrating it into my frontend code and unsure how to pro ...

Unable to append to the array

I am currently experimenting with using React to create a sorting visualizer. I am encountering an issue where the array does not update in line 31 for some unknown reason. Strangely, when I check the console log, the updated array is being logged. impo ...

I'm having trouble with the live sass compiler plugin in vs code - it's not syncing up with my css file properly

click here for image description I am facing an issue where my CSS file is not translating the codes in my SCSS file properly and adding unwanted comment lines. If anyone has insights on why this might be happening, I would greatly appreciate it. ...

Ensure that the view is only updated once the JSON has been completely received from the AJAX call in AngularJS

Just starting out with angularJS and still in the learning phase. I'm currently working on creating a navbar for the header that will fetch data from an ajax call. The issue I'm facing is that it displays {{obj.pageData}} until the data is fully ...

What causes an AJAX POST request to fail?

While working on a simple HTML page with a form, I encountered an issue with my POST request failing without any response from the server. Can someone please help me figure out what I'm doing wrong? function createRequest(url, body) { var respons ...

Include an item in a Vuetify model's array of objects

Currently, I am attempting to store the value of a dynamically loaded radio button into an array of objects. These radio buttons serve as options for a set of questions within a form, and my desired output is as follows: [{"question1":{ " ...

Is there a way to conceal the headers during an ajax request?

I'm currently exploring APIs using jQuery and Ajax. To set the header of Ajax, I typically use code similar to this: headers: { "My-First-Header":"first value", "My-Second-Header":"second value" }, I am working on a basic school project and ...

Why is the value in my React Redux state not updating as expected?

I recently started learning react js as a beginner. To practice, I created a crud app and integrated firebase for authentication. However, I'm facing an issue where I'm not able to retrieve the updated value. Index.jsx At line 11, I'm stru ...