Dealing with the challenge of having multiple types in a single dynamic type within Typescript when using

I had the idea to use various types under a single 'dynamic' type, so I created:

export type ICandidate = 
  | ICandidatePlain
  | ICandidateTalented
  | ICandidateExperienced

The reason for this is because objects in the candidates array may have different properties from one another.

This ICandidate type worked well as candidates were just a part of the object:

export interface Process {
  id: string,
  name: string,
  candidates: ICandidate[]
}

The issue arose later when I needed to map all candidates to their specific component (which depends on type).

Here is a link to codesandbox, error on line #14

Is there a better way to make this work?

I suspect that the map function expects an array of objects with identical properties - or objects of type ICandidate but not mixed types. How can I make it work with mixed types inside a single array?

My current workaround is using any for the type like

data.map((candidate: any)=>{...}
, but I would prefer to find a solution with proper typing rather than just hacking around.

Answer №1

Within your exampleObject.ts, the code snippet indicates:

//...
data: [
    {
      type: "plain",
      //...
    },
    {
      type: "talented",
      //...
    },
    {
      type: "experienced"
      //...
    }
  ]
...

An issue arises here as TypeScript automatically widens the type of type to string by default (rather than

"plain" | "talented" | "experienced"
) causing it to miss detecting your discriminator field. To address this, you must either declare a separate variable with annotation:

const data : ICandidate[] = [...];

or include as const throughout to prevent TypeScript from widening the type:

data: [
    {
      type: "plain" as const,
      //...
    },
    {
      type: "talented" as const,
      //...
    },
    {
      type: "experienced" as const,
      //...
    }
  ]

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

Having trouble with Angular's ActivatedRoute and paramMap.get('id')?

Currently, I am attempting to retrieve information from my server using the object's ID. The ID can be found in the URL as well: http://xyz/detail/5ee8cb8398e9a44d0df65455 In order to achieve this, I have implemented the following code in xyz.compo ...

Whenever I navigate to a new page in my NEXTJS project, it loads an excessive number of modules

I am currently working on a small Next.js project and facing an issue where the initial load time is excessively long. Whenever I click on a link to navigate to a page like home/product/[slug], it takes around 12 seconds to load due to compiling over 2000 ...

When selecting a MenuItem, only a ReactOwner has the ability to add a ref using addComponentAsRefTo(...)

I'm currently working on a basic component that looks like this: class App extends React.Component<{}, {}> { constructor() { super(); } render() { return ( <MuiThemeProvider muiTheme={muiTheme}> <div> ...

In Typescript, is it correct to say that { [key: string]: any } is identical to { [key: number]: any }?

Recently diving into Typescript has been an interesting journey, especially when stumbling upon weird language behaviors. After writing the following code snippet, I was surprised to see that it compiled and executed successfully: let x: { [key: string]: a ...

Detecting incorrect serialized data entries based on data types

In the scenario where the type MyRequest specifies the requirement of the ID attribute, the function process is still capable of defining a variable of type MyRequest even in the absence of the ID attribute: export type MyRequest = { ID: string, ...

Avoiding the insertion of duplicates in Angular 2 with Observables

My current issue involves a growing array each time I submit a post. It seems like the problem lies within the second observable where the user object gets updated with a new timestamp after each post submission. I have attempted to prevent duplicate entr ...

Is it possible to design a Typescript type that only contains one property from a defined set and is indexable by that set as well?

I have the different types listed below: type OrBranch = { or: Branch[] } type AndBranch = { and: Branch[] } I need a type called Branch that can either be an OrBranch or an AndBranch. I initially attempted this: type Branch = AndBrand | OrBranch ...

Including a Javascript library (jsencrypt) in an Angular 2 application

I have gone through countless tutorials on this particular issue, but unfortunately, I have not yet found a solution. Let me provide some context first. I am working on an Angular 2 application and I need to incorporate this JS library for encryption: http ...

Issue with Readonly modifier not functioning as expected in Angular/Typescript

My goal is to create a component property that is read-only. However, I am facing an issue where the readonly modifier does not seem to have any effect. View example on stackblitz According to the documentation, once I initialize the cars property in the ...

How can you verify the correctness of imports in Typescript?

Is there a way to ensure the validity and usage of all imports during the build or linting phase in a Typescript based project? validity (checking for paths that lead to non-existent files) usage (detecting any unused imports) We recently encountered an ...

Accelerated repository uses TypeScript to compile a node application with dependencies managed within a shared workspace

Struggling to set up an express api within a pnpm turborepo workspace. The api relies on @my/shared as a dependency, which is a local workspace package. I have been facing challenges in getting the build process right. It seems like I need to build the s ...

Setting checkbox values using patchValue in Angular programming

I'm facing an issue with reusing my create-form to edit the form values. The checkbox works fine when creating a form, but when I try to edit the form, the values don't get updated on the checkbox. Below is the code snippet that I have been worki ...

Tips for customizing the `src/app/layout.tsx` file in Next.js 13

I am looking to customize the layout for my /admin route and its child routes (including /admin/*). How can I modify the main layout only for the /admin/* routes? For example, I want the / and /profile routes to use the layout defined in src/app/layout.ts ...

Passing parameters by reference in TypeScript

It is possible to pass parameters by reference in C#. For example: private void Add(ref Node node) { if (node == null) { node = new Node(); } } Add(ref this.Root); After executing Add(ref this.Root), th ...

The API endpoint code functions perfectly in Express, but encounters an error when integrated into Next.js

Express Code: app.get('/', async (req, res) => { const devices = await gsmarena.catalog.getBrand("apple-phones-48"); const name = devices.map((device) => device.name); res.json(name); }) Nextjs Code: import {gsmarena} ...

Refine current attributes of an object in Typescript

In typescript, I have an object of type any that needs to be reshaped to align with a specific interface. I am looking for a solution to create a new object that removes any properties not defined in the interface and adds any missing properties. An exam ...

Is it feasible to broaden an interface in Typescript without including a specific type?

import React from "react"; interface a_to_e { a?: string; b?: string; c?: string; d?: string; e?: string; } interface a_to_e_without_c extends a_to_e { // I want to include properties a~e except for c } function Child(props: a_to_e_without_c ...

Ensuring strictNullChecks in Typescript is crucial when passing values between functions

When using the --strictNullChecks flag in TypeScript, there seems to be an issue with inferring that an optional property is not undefined when the check occurs in a separate function. (Please refer to the example provided, as articulating this clearly is ...

Execute an npm script using a gulp task

Is there a way to execute an npm script command within a gulp task? package.json "scripts": { "tsc": "tsc -w" } gulpfile.js gulp.task('compile:app', function(){ return gulp.src('src/**/*.ts') .pipe(/*execute npm run tsc*/ ...

What is the best way to create an HTML form on-the-fly from a JSON object?

Could someone please assist me in understanding how to dynamically generate an HTML form based on a JSON object using JavaScript? ...