Exploring the differences in object shapes using TypeScript

I'm currently working on defining an object that has the ability to hold either data or an error.

export type ResultContainer = {
  data: any;
} | {
  error: any;
};

function exampleFunction():ResultContainer {
    return {
        data: 3
    }
}

However, when attempting to access the result of the function, I encounter the following issue:

const result = exampleFunction();
result.data = 23; // Property 'data' does not exist on type 'ResultContainer'. Property 'data' does not exist on type '{ error: any; }'

Could someone guide me on the correct way to access either 'data' or 'error'? Thank you!

Answer №1

Here is TypeScript's interpretation of your code:

const v = test();
// v: {data: any} | {error: any}
v.data = 23;
// There is a possibility that 'v' could be of type '{error: any}'
// If so, there may be a runtime error
// To avoid this error, let's throw a TS error now!

To prevent this from happening, you can use a type guard to narrow down the union type to a specific type that won't lead to a TS error:

const v = test();
// v: {data: any} | {error: any}
if ('data' in v) {
  // v: {data: any}
  v.data = 23;
  // no error will occur!
}

If you are confident that v will have a property named data, you can cast v during its declaration:

const v = (test() as {data: any});
v.data = 23;

You can experiment with this code on the typescript playground

Answer №2

Check out this implementation featuring a discriminated union structure (including the addition of a shared property called dataType in each union member):

export type Outcome = {
  dataType: "result",  
  resultData: any
} | {
  dataType: "failure",  
  errorMessage: any
};

function assess(): Outcome {
    return {
        dataType: "result",
        resultData: 5
    }
}

const res = assess();
if ("result" === res.dataType){
   res.resultData = 45;
}

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

tips for accessing dynamic key pair value data in Angular

I am facing an issue where I cannot retrieve the dynamic key pair value from the dynamic JSON. Below is my JSON: var d = { "pexels-photo.jpeg": { "information": "laptop", "desc": { "mimetype": "image/jpeg", "id" ...

registering a back button action in Ionic2 for multiple pages

Currently, I am in the process of developing my Ionic2 app and have encountered a dilemma regarding the functionality of registerBackButtonAction. On one page, let's call it pageA, I have implemented this function and everything is functioning as exp ...

What is the proper way to create a React Context in TypeScript that accepts both a ref and a setState function as arguments?

When encountering various errors, one of them being: Type 'Dispatch<SetStateAction<null>>' is not assignable to type '() => void' My code looks something like this: import React, { ReactElement, ReactNode, useEffec ...

Is it possible to automatically correct all import statements in a TypeScript project?

After transferring some class member variables to a separate class in another file, I realized that these variables were extensively used in the project. As a result, approximately 1000 .ts files will need their imports modified to point to the new class/f ...

Is there a way to programmatically add a timestamp to a form in Angular6?

Is there a way to automatically populate new forms with the current datetime value? this.editForm.patchValue({ id: chatRoom.id, creationDate: chatRoom.creationDate != null ? chatRoom.creationDate.format(DATE_TIME_FORMAT) : null, roo ...

When evaluating objects or arrays of objects to determine modifications

How can we detect changes in table data when users add input to cells? For example, if a user clicks on a cell and adds an input, the function should return TRUE to indicate that there are changes. If the user just clicks on the cell without making any ch ...

Challenges of Vue 3 Typescript ComputedRef

I've run into some challenges with Typescript and Vue3. It seems like I might be using Typescript incorrectly in this case. I set up a store using Vue's Composition API. import {computed, reactive} from "vue"; const state = reactive({ ...

Tips for telling the difference between typescript Index signatures and JavaScript computed property names

ngOnChanges(changes: {[paramName: string]: SimpleChange}): void { console.log('Any modifications involved', changes); } I'm scratching my head over the purpose of 'changes: {[propName: string]: SimpleChange}'. Can someone cl ...

Ways to dynamically display or hide content in Angular 7

>when an English button is clicked, its corresponding div should be shown. If another button is clicked, its div should also show without closing the previous one. I want each div to close only when its respective button is clicked again. >Please not ...

Utilize mui-tiptap to effortlessly upload images to your content

My current project involves using the mui-tiptap module in React 18 with Vite. Specifically, I am facing an issue with uploading a local image to my backend. The problem seems to lie in my frontend code, as I am encountering a TypeScript error that is prev ...

What is the best way to combine TypeScript output while maintaining node import integrity?

Currently, I am combining the results of the typescript compiler using this particular technique. However, this process is causing issues with the imports of relative path modules in Node. The code below compiles and merges successfully; // Group.ts clas ...

Transferring data from a child component to a parent component in Angular using @ViewChild requires providing 2 arguments

Currently, I am attempting to transmit data using @Output & EventEmitter and @ViewChild & AfterViewInit from a child component to a parent component. Below is the code from my parent component .html file: <app-child (filterEvent)=" getValu ...

Make sure to declare rest parameters first when using Typescript

I am dealing with a function that takes in multiple string arguments and one final argument of a complex type, which is called Expression. This particular code looks like this in JavaScript: function layerProp(...args) { const fields = args.slice(0, -1) ...

The devastation caused by typing errors in TypeScript

I have a preference: const settings = { theme: "light", }; and feature: const Feature = ({ setting }: Props) => ( <FeatureBlock> <FeatureValue scale="large" size={20}> {setting.theme} </Styled.FeatureValue> ...

Remove the package from the @types folder within the node_modules directory

I currently have the 'mime' library in my node_modules directory and I am looking to completely remove it from my project, along with its @types files. The reason for this is that the old mime package is not functioning correctly for me, so I wan ...

Retrieve the instance from the provider using its unique key without needing to inject its dependencies

I created a custom class called PermissionManager, which takes a list of Voter interfaces as an input in its constructor. export interface Voter { vote(): bool; } export class PermissionManager { constructor(private readonly ...

Utilize the expert capabilities within #dateHeaderTemplate in the Angular component schedule by Syncfusion

I am trying to access the template #dateHeaderTemplate in order to retrieve the ID of the professional who is scheduled to attend the appointment. This information is needed to display the start and end times of the day in the header. By visiting this lin ...

What distinguishes between a public variable declared as var: any = []; versus a public variable declared as var: any[] =

I'm seeking clarification on the distinction between the following: public var: any = []; // versus public var: any[] = []; ...

Angular: Safely preserving lengthy content without the use of a database

As a beginner working on an Angular 11 educational website with approximately 20 static articles, I created a component template for the articles to receive text inputs. However, I am wondering if there is a more efficient way to handle this. Is there a ...

I am unable to locate the appropriate TypeScript type for the `displayName` attribute when it is used as a prop for the `type` component

Having trouble finding the correct type as mentioned in the title. After inspecting with DevTools, I have confirmed that every component I am programmatically looking at has Component.type.displayName. For anything that is not an ElementType, the type is a ...