Refine a union type by considering the properties already defined in an object

interface CustomHTMLElement {
  htmlPropA: string,
  htmlPropB: string,
}

interface CustomHTMLInput {
  inputPropA: string,
  inputPropB: string,
}

type CustomElement =
  | CustomHTMLElement
  | CustomHTMLInput

const element: CustomElement = {
  inputPropA: 'bar', // implies that this is a CustomHTMLInput
  h // intellisense shows htmlPropA, htmlPropB here, indicating it could also be a CustomHTMLElement 
    // and not just a CustomHTMLInput as previously implied by the presence of inputPropA
}

Even with inputPropA already existing in the object, intellisense will display both htmlPropA and htmlPropB, potentially causing confusion about the type of the element. Is there a better way to specify the typing so that intellisense only suggests properties for either CustomHTMLInput or CustomHTMLElement instead of both?

Answer №1

The property buttonPropA does not act as a discriminator for the union type because it is permitted by the MockHTMLDivElement type. This means that an object like

{buttonPropA: 'foo', divPropA: 'bar', divPropB: 'baz'}
can be considered a valid value of type MockHTMLDivElement.

If you switch to using a discriminated union, only the properties from the defined subtypes will be suggested. In this case, the discriminant is kind.

interface MockHTMLDivElement {
  kind: 'div',
  divPropA: string,
  divPropB: string,
}

interface MockHTMLButtonElement {
  kind: 'button',
  buttonPropA: string,
  buttonPropB: string,
}

type MockElement = MockHTMLDivElement | MockHTMLButtonElement

const el: MockElement = {
  kind: 'button',
  buttonPropA: 'foo',
  b, // suggestions include 'buttonPropB'
  d, // no suggestions
}

Playground Link

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

Utilizing Typescript for parsing large JSON files

I have encountered an issue while trying to parse/process a large 25 MB JSON file using Typescript. It seems that the code I have written is taking too long (and sometimes even timing out). I am not sure why this is happening or if there is a more efficien ...

Begin the NextJS project by redirecting the user to the Auth0 page without delay

I am new to coding and currently working on a project using Typescript/NextJS with Auth0 integration. The current setup navigates users to a page with a login button that redirects them to the Auth0 authentication page. However, this extra step is unneces ...

Why does the method of type assigning vary between actual and generic types?

There are no errors in the code shown below: type C = {b: string}; class Class { data: C; constructor(data: C) { this.data = data; } test() { const hack: C & {a?: any} = this.data; //no error } } However, when a g ...

Angular 4 file upload verification: Ensuring safe and secure uploads

Is there a recommended method to validate the file type when uploading a file in an Angular 4 form? Are there any simple ways to accomplish this task? ...

Tips for changing a function signature from an external TypeScript library

Is it possible to replace the function signature of an external package with custom types? Imagine using an external package called translationpackage and wanting to utilize its translate function. The original function signature from the package is: // ...

Implementing setDoc with Firebase-Admin using Typescript in Firestore

I'm having issues with my code in config/firebase.ts: import { initializeApp, cert } from 'firebase-admin/app'; import { getFirestore } from 'firebase-admin/firestore' const firebaseAdminApp = initializeApp({ credential: cert( ...

Encountering an Issue with Passing Props through Gatsby Link to Access a Prop on the

I am encountering an issue when trying to pass a value to another page for conditional rendering. The bug I'm facing is related to 'location' being undefined during the build process. Despite my efforts, I have been unable to resolve this is ...

Angular: Implementing default nested routes

I am currently facing a challenge with routing in my Angular application. I have set up a page within a router-output on the route /products. This page contains another router-output which will display one of two possible children routes (/products/profess ...

I'm encountering an issue where my query parameter is not being accepted by the tRPC query request

I encountered an issue when I tried sending a request to http://localhost:5000/trpc/test?val=teststring using the minimal reproducible example below. The response message received was "Invalid input: undefined," indicating that the value 'val' is ...

What type of HTML tag does the MUI Autocomplete represent?

Having trouble calling a function to handle the onchange event on an autocomplete MUI element. I've tried using `e: React.ChangeEvent`, but I can't seem to locate the element for the autocomplete component as it throws this error: The type &apos ...

Having an excess of 32 individual byte values

My current project involves developing a permission system using bitwise operators. A question came up regarding the limitation of having only 32 permissions in place: enum permissions { none = 0, Founder = 1 << 0, SeeAdmins = 1 << ...

Tabulate the number of items in an array based on the month and

I have received JSON data with dates indicating the creation time of multiple parcels. I want to analyze this data and calculate the total number of parcels created in each month. I am new to this process and unsure about which thread on Stack Overflow can ...

Handling errors in nested asynchronous functions in an express.js environment

I am currently developing a microservice that sends messages to users for phone number verification. My focus is on the part of the microservice where sending a message with the correct verification code will trigger the addition of the user's phone n ...

Setting up a Node.js project in your local environment and making it

I need help installing my custom project globally so I can access it from anywhere in my computer using the command line. However, I've been struggling to make it work. I attempted the following command: npm install -g . and some others that I can&ap ...

Implementing pagination for an Angular Material table using an HTTP request to set the page

How can I update the table page index when users click on next and previous buttons in an API that fetches data based on a specified Page number? It's important to note that I have already created a shared table. @Input() columns: Column[] = []; @In ...

Break free/Reenter a function within another function

Is there a way to handle validation errors in multiple task functions using TypeScript or JavaScript, and escape the main function if an error occurs? I am working in a node environment. const validate = () => { // Perform validation checks... // ...

Can you explain the distinction between the controls and get methods used with the FormGroup object?

I have encountered an interesting issue with 2 lines of code that essentially achieve the same outcome: this.data.affiliateLinkUrl = this.bookLinkForm.controls['affiliateLinkUrl'].value; this.data.affiliateLinkUrl = this.bookLinkForm.get(' ...

Gaining entry to a static member of an exported class in a module

I am facing an issue with my Typescript code snippet. The code is as follows: module MyModule { export class MyClass { static MyStaticMember : string; } } My requirement is to access this code from a separate file after compilation. I tri ...

Having trouble with Angular 2 @input binding?

Parent module: import {NgModule} from '@angular/core'; import {SharedModule} from "app/shared/shared.module.ts"; import {HeaderComponent} from './header.component'; import {UserinfoComponent} from './userinfo.component'; imp ...

Utilize a variable from one Angular component in another by sharing it between .ts files

My issue involves dynamically adding items to a todo list and wanting to exclude certain items. The challenge lies in the fact that the list itself is located outside of the task component: Within the task.component.html file, I iterate through the list f ...