TS does not approve of optional chaining when it comes to objects

type Object1 = {
  link: 'niceurl.com'
}

type Object2 = {
  source: 'differenturl.com'
}

function AnotherComponent(item: Object1 | Object2) {
  return (
    <img src={item?.link || item?.source} />
  )
}

Output:

Error: 
Property 'link' does not exist on type 'Object1 | Object2'.
  Property 'link' does not exist on type 'Object2'

Expected: no error as the optional chaining meets the type guard.

I think something like ("link" in item) or a similar inline type assertion might help, but considering the component's size, these options seem cumbersome.

Answer №1

This scenario is commonly seen in TypeScript. When using optional chaining, TypeScript can struggle to determine the correct types.

function DisplayImage(item: Obj1 | Obj2) {
  return (
    <img src={"url" in item ? item.url : item.src} />
  )
}

If you feel that checking "xx" in obj every time is too cumbersome, you could create a discriminated union for Obj1 and Obj2 like this.

type Obj1 = {
  url: 'coolurl.com'
  src?:undefined
}

type Obj2 = {
  src: 'someurl.com'
  url?:undefined
}

function DisplayImage(item: Obj1 | Obj2) {
    
  return (
    <img src={ item.src ?? item.url} />
  )
}

Answer №2

If you ever find yourself needing to narrow down the type in your code, consider using a type predicate. For instance, you can create a function that narrows the item to one of two types in your code: Check out this Playground

type Object1 = {
  url: 'coolurl.com'
}

type Object2 = {
  src: 'someurl.com'
}

function isObject1(obj: Object1 | Object2): obj is Object1 {
    return (obj as Object1).url !== undefined;
}

function MyComponent(item: Object1 | Object2) {
  return (
    <img src={isObject1(item) ? item.url : item.src} />
  )
}

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 prerender.io with lazy loading in Angular 2: A comprehensive guide

As Angular Universal is not expected to be included in the CLI for some time, I've had to resort to using prerender.io in order to ensure proper SEO functionality. However, my tests have shown that there are issues with lazy loaded modules causing SEO ...

Error: No 'map' property found in 'TwitterserviceService' type

Currently, I am in the process of learning how to develop simple and basic Angular applications. As part of my learning journey, I decided to incorporate my Twitter timeline into one of my projects. To aid me in this endeavor, I referred to various online ...

How come webstorm/react-hook-forms isn't showing me suggested choices for the "name" field?

I'm looking to create components with inputs, but I'm currently facing an issue with tooltips not showing for the name. I would like the form fields to display the name. export const Form: FormType = ({ children, form }) => ( <FormProvide ...

Update the name of the table header dynamically based on the checkbox that is selected in Vue

I am working on a project where I have checkboxes that determine the header of my table based on selection. Starting from <th>Default</th>... If checkbox1 is checked, the header will change to "CheckBox1". If checkbox2 is checked, the header ...

How to add a service to a static function in Angular

After incorporating a logger service into my project, I have encountered an issue with using it in NGXS static selectors. The selectors in NGXS are static methods, which prevent me from accessing the logger service injected via Angular DI. Are there any e ...

Unable to retrieve dynamically generated object property from an array in AngularJS 2+

Here is an example of an items array: this.itemList = [ { id: 1, name: 'a', address: 'as dasf a' }, { id: 2, name: 'b', address: 'as dasf a' }, { id: 3, name: 'c', address: 'as dasf a' } ]; ...

Toggle the visibility of a checkbox based on the JSON data

I have 4 check boxes that need to be dynamically displayed based on the value retrieved from my JSON. The JSON will only contain one checkbox name, and that specific checkbox should be shown to the user as checked. How can I achieve this functionality? Bel ...

Combine the values in the array with the input

I received some data from the back-end which is being written to a form, and it's in the form of an array of objects Below is the code snippet: this.companyDetailsForm = new FormGroup({ directors : new FormControl(response?.companyDirectors) ...

Unable to access or modify properties within a function passed as an argument

deleteDialog(item, func: Function) { this.dialogService .open(ConfirmDialogComponent, { context: { title:"Are you sure?", cancelClss: "info", confirmClss: "danger", }, ...

When accessing an Angular 7 page directly through the URL in the browser, it becomes unresponsive. However, the page works perfectly fine when navigating

I've been tackling a poorly developed Angular 7 legacy application and encountering a bizarre issue. There's a component that requires a parameter for email verification, but when the URL is visited directly, it doesn't function as expected. ...

A guide to accessing parent attributes in Vue3 using typescript

Within my child component, I am facing an issue where I need to access the parent object but the commented lines are not functioning as expected. The structure of AccordionState is defined below: export type AccordionKeys = | "open" | "disa ...

What is the method for utilizing an alias at the top within a subquery?

Is it possible to use an alias from the top query in a subquery? I am currently encountering an error with 'artc'. let myQuery = this.articles.createQueryBuilder('artc') .select(['artc.title']) .addSelect(qb => ...

The index declaration file has not been uploaded to NPM

After creating a Typescript package and publishing it on NPM, I encountered an issue with the declaration files not being included in the published version. Despite setting declaration: true in the tsconfig.json, only the JavaScript files were being publis ...

Tips for setting up a React TypeScript project with custom folder paths, such as being able to access components with `@components/` included

I'm looking to streamline the relative url imports for my React TypeScript project. Instead of using something messy like ../../../contexts/AuthContext, I want to simplify it to just @contexts/AuthContexts. I attempted to update my tsconfig.json with ...

Can you explain the key distinction between the backtick (`) and the ampersand-hash-39

I am completely new to TypeScript, JavaScript, and Angular. As I follow some tutorials, I often encounter code snippets like the one below: class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return `(${this.x}, ${th ...

Creating a type-safe dictionary for custom theme styles in Base Web

In my Next.js project, I decided to use the Base Web UI component framework. To customize the colors, I extended the Theme object following the guidelines provided at . Interestingly, the documentation refers to the theme type as ThemeT, but in practice, i ...

Sending data using formData across multiple levels of a model in Angular

I have a model that I need to fill with data and send it to the server : export interface AddAlbumeModel { name: string; gener: string; signer: string; albumeProfile:any; albumPoster:any; tracks:TrackMode ...

Utilizing Express JS to Optimize JPEG File Loading with Cache Headers

I have been working on implementing Cache-Control for my static image files. I have successfully set this header for HTML and JS files: https://i.stack.imgur.com/9VuWl.png However, I am facing challenges with JPEG files: https://i.stack.imgur.com/p52jm. ...

Discovering how to specify the type of a dynamically created object using 'for await' in TypeScript

for await (user of users) { ... } Encountered an issue: "error TS2552: Cannot find name 'user'. Did you mean 'users'?" Appreciate your assistance. ...

Oh no! It seems like the build script is missing in the NPM

https://i.stack.imgur.com/el7zM.jpg npm ERR! missing script: build; I find it strange, what could be causing this issue? Any suggestions? I have included the fullstack error with the package.json. Please also review the build.sh code below. Fullstack err ...