I am having trouble with a property that I believe should be recognized but is not

Here is the vocabulary I am working with:

type MyHeaders = {
  Authorization: string;
  Accept: "application/json";
};
type MyGetOptions = {
  url: string;
  json: true;
};
type MyOptionsWithHeaders = {
  headers: MyHeaders;
};
type MyPostOptions<T> = MyGetOptions | {
  body: T;
};
type MyPostOptionsWithHeaders<T> = MyPostOptions<T> | MyOptionsWithHeaders;
type MyBodyType = {};
type APICallOptions = MyPostOptionsWithHeaders<MyBodyType>;

An error is occurring in the following code under the "url" in "temp.url": "Property 'url' does not exist on type 'BatchSubmissionOptions'. Property 'url' does not exist on type 'OptionsWithHeaders'.ts(2339)"

const temp: APICallOptions = {
  url: "url",
  headers: {
    Authorization: "Bearer token",
    Accept: "application/json",
    },
  body: {
    some: "stuff",
    more_stuff: []
  }
}
temp.url = "Hello"

I am attempting to create a vocabulary that allows me to specify arguments like "BatchSubmissionOptions" for a specific query to an internal server API. I want to define options as Post, Post with authentication headers, Get, or Get with authentication headers. The issue arises when trying to set properties after initialization.

Could there be a mistake in my definitions that I am overlooking?

EDIT: Following the recommendation of CodeQuiver, I have adjusted the code with more standardized separators based on the referenced article. Although sound advice, it did not fix the problem at hand.

Side note: While simplifying this problem for the question, I noticed that it doesn't flag an error when the value of "body" doesn't match MyBodyType, allowing different values. It only validates correctly when defining properties in MyBodyType; perhaps this is due to defining an object as {}?

Answer №1

If you have a variable declared with a union type, for example:

let temp: A | B;

You can only access properties that are common to both types when using that variable. This limitation is in place to prevent accessing non-existent properties (which could potentially lead to program crashes) since the compiler cannot determine which specific type the variable will resolve to.

For example:

We have defined two types A and B, each with an overlapping property id:

type A = {
    id: number;
    title: string;
    text: string;
}

type B = {
    id: number;
    flag1: boolean;
    flag2: boolean;
}

The following code snippet will work without any issues:

const id = temp.id;

However, attempting to access a property unique to one of the types will result in an error message:

const text = temp.text;   // <--- Error: "text" does not exist in B

On the other hand, if you assign an object literal, you must include at least one unique property so that the compiler can infer the correct type and warn you about missing properties:

This would throw an error (

Type '{ id: number }' is missing the following properties from type 'B': flag1, flag2
):

let temp: A | B = {
    id: 1
};

To resolve this issue, you need to include additional unique properties so the compiler can determine the appropriate type. For instance, the following declaration specifies type A:

let temp: A | B = {
    id: 1,
    title: "Title"
};

If you don't include the required text property as part of type A, the compiler will raise an error. You can also add properties from type B</code, given that <code>temp is assigned a union type:

let temp: A | B = {
    id: 1,
    title: "Title",
    text: "Text",
    flag1: true
};

Answer №2

It seems like the main issue here is a simple typo. The members of your type literal are not separated properly:

type MyGetOptions = {
  url: string
  json: true
}

In Typescript, you need to separate members using either semicolons or commas, like in this example:

type MyHeaders = {
  Authorization: string,
  Accept: "application/json",
}

This could be why the 'url' property is not being recognized initially.

While there may be more complex issues at play, it's best to address the simpler problem first as it might solve everything. Check out this article for more insights: https://medium.com/swlh/typescript-best-practices-delimiters-and-ordering-7feb42e0ca1d (I couldn't find direct reference to this syntax in the Typescript documentation, so I'm referencing Medium instead, which also uses semicolon separators in its examples.)

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

What is the method for incorporating opacity into the background color CSS attribute using a Fluent UI color?

Currently, my challenge involves applying opacity to a background color sourced from the fluent UI library, which utilizes Design Tokens. Typically, I would add opacity to a background color like this: background-color: "rgba(255, 255, 255, 0.5)" However ...

The message states that the variable "Chart" has not been defined

I have been attempting to integrate ChartJS with Angular2, but I keep encountering an error message stating that 'Chart is not defined'. I made sure to install the ChartJS typings and referenced them accordingly. Additionally, I included the char ...

Invalid sequencing of Nest.js async onModuleInit causing issues

I am dealing with a scenario where ServiceA relies on RedisService. In order for ServiceA to be fully operational, it must wait for RedisService to complete its initialization process (specifically, for RedisService.onModuleInit to be called and awaited). ...

The value of this.$refs.<refField> in Vue.js with TypeScript is not defined

During the process of converting my VueJs project to TypeScript, I encountered an error related to TypeScript. This issue arises from a component with a custom v-model implementation. In the HTML, there is an input field with a 'plate' ref that ...

When deploying my Angular project, I am unable to access my files

I have been facing challenges while trying to deploy my web application with the frontend being Angular. The issue I am encountering is that I cannot access my JSON file located in the assets folder. Below is the function I am using to retrieve data from ...

Is there a way to run the mediapipe face detection codepen.io demo on my laptop?

After successfully running the mediapipe face detection demo from Mediapipe official website, I wanted to replicate it on my laptop. To achieve this, I created an 'index.html' file and meticulously transferred the code from the CodePen demo page ...

Encountering a 'No overload matches this call.' error when using ApexCharts with Typescript and ReactJS

As a newcomer to Typescript, I am gradually familiarizing myself with this powerful tool. After fetching the OHLCV data from coinpaprika and passing it to ApexCharts, I encountered an issue while trying to map the raw data: ERROR in src/routes/Chart.tsx:3 ...

Why is Axios not being successfully registered as a global variable in this particular Vue application?

Recently, I have been delving into building a Single Page Application using Vue 3, TypeScript, and tapping into The Movie Database (TMDB) API. One of the hurdles I faced was managing Axios instances across multiple components. Initially, I imported Axios ...

The fusion of Typescript with Node.js

Currently, I am delving into learning typescript and exploring how to integrate it with Node.js. After watching multiple educational videos, I came across two distinct methods for linking typescript with Node.js. The first method involves using decorators, ...

Challenges with importing and using jspdf and autotable-jspdf in Angular 8

Issue with Generating PDF Using Angular 8, JSPDF, and JSPDF-AutoTable I am facing a challenge with exporting/generating a PDF based on an HTML grid. I need to make some DOM changes with CSS, remove toggle buttons, alter the header, etc. However, all the s ...

Tips for asynchronously updating a model in TypeScript

I have been working on a function to hide the element for connecting to Facebook upon successful connection. I have implemented two functions, success and error, which trigger after Firebase successfully logs in the user. While I can confirm that these fun ...

The issue encountered is: "Unable to assign property 'id' to a numeric value of '1' in Angular."

In my Angular 7 project, I am trying to establish a client-side request to the server-side. Below is the structure of the request that needs to be sent. { "title" : "Test Title", "user": { "id" : 7 ...

Adjust the colors dynamically based on specific data within a loop

My task involves populating a table with data. Specifically, I am focusing on coloring the data in the first year column according to certain conditions. The desired outcome is as follows: +--------+------------+------+------+ | YEAR | 2022 | 2021 ...

Enhancing Application Performance Through Next.js Development

I'm currently working on an application using next.js and I am looking to implement code splitting in order to reduce the bundle size and load pages on demand. Unfortunately, I have not been able to find a way to do this without specifying routes. Fo ...

TypeScript interface with an optional parameter that is treated as a required parameter

Within my interface, I have a property that can be optional. In the constructor, I set default values for this property, which are then overridden by values passed in as the first parameter. If no properties are set, the defaults are used. I am looking fo ...

Here's a method to extract dates from today to the next 15 days and exclude weekends -Saturday and Sunday

Is there a way to generate an array of dates starting from today and spanning the next 15 days, excluding Saturdays and Sundays? For example, if today is 4/5/22, the desired array would look like ['4/5/22', '5/5/22', '6/5/22' ...

What is the proper way to declare an array of arrays with interdependent types?

Imagine I am creating a directory of tenants in a shopping center, which can be either shops or restaurants. These tenants fall into various categories: type ShopTypes = | `Accessories` | `Books` | `Clothing`; type RestaurantTypes = | `Div ...

Leveraging Global Variables and Functions with Webpack and TypeScript

I have been utilizing Webpack in conjunction with TypeScript, HTML, and SCSS to develop a project. My goal is to create a single page application that incorporates a router located within the root folder of the project /framework/, with all my source code ...

Create a series of actions that do not depend on using only one occurrence of the WriteBatch class

My goal is to create a series of batch actions using functions that do not require a specific instance of WriteBatch. Currently, I am passing an instance of the WriteBatch class to the functions so they can utilize the .set(), .update(), or .delete() metho ...

Subtracted TypeScript concept

Is it possible to create a modified type in Typescript for React components? import {Component, ComponentType} from 'react'; export function connect<S, A>(state: () => S, actions: A){ return function createConnected<P>(componen ...