The attribute is not found on the combined type

After combing through various questions on stackoverflow, I couldn't find a solution to my specific case.
This is the scenario:

interface FruitBox {
  name: string
  desc: {
   'orange': number;
   'banana': number;
  }
}

interface IceBox {
  name: string
}

interface Vegabox {
  name: string
  desc: {
   'tomato': number;
   'potato': number;
  }
}

type UnionBox = FruitBox | Vegabox | IceBox;

My Implementation Attempt:

type Ship = Record<string, (description: UnionBox['desc'] | UnionBox['name']) => void>;

I am aiming to assign a description property to either UnionBox['desc'] or UnionBox['name'] if the desc parameter is not present.

The following error is appearing:

Property 'desc' does not exist on type 'UnionBox'

Any assistance or guidance would be greatly appreciated.

ps. I realize there might be a complex algorithm involved, I'm just unsure which direction to take

Answer №1

Take a look at this solution. It addresses a similar scenario.

When TypeScript resolves union types, it identifies the best common type to use - which is the type that is common among all elements in the union. This approach ensures safety.

Let's analyze your union:

interface FruitBox {
  name: string
  desc: {
   'orange': number;
   'banana': number;
  }
}

interface IceBox {
  name: string
}

interface Vegabox {
  name: string
  desc: {
   'tomato': number;
   'potato': number;
  }
}

type UnionBox = FruitBox | Vegabox | IceBox;

type AllowedKeys = keyof UnionBox // name

By defining AllowedKeys, you are restricted to only using the name property from the UnionBox. This limitation exists because name is present in each part of the union.

To handle this situation, consider implementing the StrictUnion helper function.

// credits goes to https://stackoverflow.com/questions/65805600/type-union-not-checking-for-excess-properties#answer-65805753
type UnionKeys<T> = T extends T ? keyof T : never;
type StrictUnionHelper<T, TAll> = 
    T extends any 
    ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;

type StrictUnion<T> = StrictUnionHelper<T, T>

Entire code snippet:

interface FruitBox {
    name: string
    desc: {
        'orange': number;
        'banana': number;
    }
}

interface IceBox {
    name: string
}

interface Vegabox {
    name: string
    desc: {
        'tomato': number;
        'potato': number;
    }
}

type UnionKeys<T> = T extends T ? keyof T : never;
type StrictUnionHelper<T, TAll> =
    T extends any
    ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;

type StrictUnion<T> = StrictUnionHelper<T, T>

type UnionBox = StrictUnion<FruitBox | Vegabox | IceBox>;

type AllowedKeys = keyof UnionBox // name


type Ship = Record<string, (description: UnionBox['desc'] | UnionBox['name']) => void>; // ok


const record: Ship = {
    foo: (elem) => { }
}

Playground

Answer №2

The example with UnionBox showcases different types such as FruitBox, Vegabox, and IceBox. However, it's important to note that IceBox lacks the property desc, which can cause issues when using it within a function that requires UnionBox as a parameter.

To workaround this issue, I am attempting to assign a value to UnionBox['desc'], defaulting to UnionBox['name'] if desc is not present.

While the logic may seem straightforward by using the | operator to create a union, implementing it in practice can be tricky. One potential solution could involve accepting unionBox: UnionBox as a parameter, then handling the scenario where desc is missing by utilizing unionBox.desc ?? unionBox.name to fallback on name.

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

Can a single data type be utilized in a function that has multiple parameters?

Suppose I have the following functions: add(x : number, y : number) subtract(x : number, y : number) Is there a way to simplify it like this? type common = x : number, y : number add<common>() This would prevent me from having to repeatedly define ...

Transferring data between unrelated components

I am facing an issue where I am unable to pass a value from the Tabs component to the Task component. To address this, I have created a separate data service. The value in the Tabs component is obtained as a parameter from another component. However, when ...

What is the process for overriding the module declaration for `*.svg` in Next.js?

The recent modification in Next.js (v11.0.x) has introduced new type definitions: For next-env.d.ts (regenerated at every build and not modifiable): /// <reference types="next" /> /// <reference types="next/types/global" /> ...

What is the best way to utilize TypeScript module augmentation with material-ui components?

I have gone through the answers provided in this source and also here in this link, but it appears that they are outdated. I attempted to enhance the type definition for the button component in various ways, including a separate typings file (.d.ts) as we ...

An error occurred when attempting to access data within a variable that is undefined, resulting in a TypeError at the errorHandler function

Every time I attempt to send a post, patch, or put request, I keep getting this error. However, there are no issues with get requests. TypeError: Cannot read properties of undefined (reading 'data') at errorHandler (/home/joe/Documents/mypro ...

Customizing Tabs in Material UI v5 - Give your Tabs a unique look

I am attempting to customize the MuiTabs style by targeting the flexContainer element (.MuiTabs-flexContainer). Could someone please clarify the significance of these ".css-heg063" prefixes in front of the selector? I never noticed them before upgrading my ...

What is the best way to hide the button when a user is viewing their own profile in an Angular application?

Each user has their own profile on the platform. A unique feature allows users to send messages by clicking a button when viewing other profiles. However, an issue arises where this messaging button also appears on a user's own profile. Is there a way ...

Creating an interface and setting a default value

I am exploring the use of interfaces in my models and want to establish a default value for them. export interface IPerson { id: string; name: string; } class Person implements IPerson { id = ''; name = 'John'; } export cla ...

Avoiding the restriction of narrowing generic types when employing literals with currying in TypeScript

Trying to design types for Sanctuary (js library focused on functional programming) has posed a challenge. The goal is to define an Ord type that represents any value with a natural order. In essence, an Ord can be: A built-in primitive type: number, str ...

Seeking out a particular key within a JSON object and then finding a match based on the id within that key's array - how can it be

Recently, I've been exploring JavaScript and encountering challenges when trying to apply array methods on objects. For instance, I received a fetch response and my goal is to extract the 'entries' key and then utilize the native Array.find( ...

Exploring the potential of Vue with Router to create a dynamic multi-page

Struggling to come up with a suitable title for this Vue project dilemma. Here's what I'm facing: Recently started using Router in my Vue project and feeling quite lost. The setup in App.vue simply includes <RouterView>, which seems stra ...

bundle.js encountered a TypeError when attempting to read a property that was undefined, specifically while trying to access the PriceIndexationDataControlStandard

In the midst of developing a React component using the Microsoft PCF Framework, I encountered a perplexing error seemingly out of the blue. While making changes in TypeScript without even executing any build commands, the rendering of my component suddenly ...

What advantages does CfnAppSync provide over using AppSync in a CDK project?

We are in the process of enhancing our API by adding new JS resolvers and phasing out the VTL resolvers for an AWS AppSync CDK project, specifically built with Cfn<> Cloud Front CDK. The code snippet below illustrates how this can be achieved: ...

Utilize Tailwind CSS in React to dynamically highlight the active navigation item on click

Check out my navigation bar code: <nav className="bg-white shadow dark:bg-gray-800"> <div className="container flex items-center justify-center p-6 mx-auto text-gray-600 capitalize dark:text-gray-300"> <Link ...

Tips for accessing a variable from a Global service in Ionic

I am currently working on developing an app using Ionic but experiencing some difficulties. I encountered an issue while trying to access a variable from a global service when it is imported to another page. Here is an example of the Global service (backen ...

Tips for modifying the language of an Angular Application's OneTrust Cookie Banner

I'm currently developing an Angular application and utilizing OneTrust for managing cookie consent. The issue I'm encountering is that while the rest of the components on the login page are properly translated into the target language, the OneTru ...

Challenge: Visual Studio 2015 MVC6 and Angular 2 compilation issue - Promise name not found

Initially, I've made sure to review the following sources: Issue 7052 in Angular's GitHub Issue 4902 in Angular's GitHub Typescript: Cannot find 'Promise' using ECMAScript 6 How to utilize ES6 Promises with Typescript? Visual ...

An Angular module downloaded from npm seems to be lacking the required @NgModule declaration

There seems to be a missing @NgModule and @Directive declarations in an NPM module, even though they exist in the source code on Github. This is causing an issue with importing a directive for databinding from an HTML attribute. I am attempting to utilize ...

Angular2: Ways to update components with resolver dependencies?

In my project, I have three separate components, each with its own resolver that retrieves data from distinct APIs. These components all depend on a shared URL provided by a service. My goal is to ensure that when the URL changes, each component refreshes ...

What are some ways to control providers in targeted tests using ng-mocks?

I recently started utilizing ng-mocks to streamline my testing process. However, I am struggling to figure out how to modify the value of mock providers in nested describes/tests after MockBuilder/MockRender have already been defined. Specifically, my que ...