"X is not compatible with these types of property," but it is not the case

I attempted to instantiate an interface object with properties initialized from another object as follows:

id: data.reference.id

Even though the properties are compatible, the TypeScript compiler is throwing an error. I am confused about why this is happening and how to resolve it.

(you can find a link to test the code below)

// INTERFACES AND TYPES
type CategoryOne = 1
type CategoryTwo = 2
type Category = CategoryOne | CategoryTwo

interface ReferenceOne {
    id: string,
    type: CategoryOne
}

interface ReferenceTwo {
    id: string,
    type: CategoryTwo
}

type Reference = ReferenceOne |  ReferenceTwo

// DIRECT INIT
let reference_OK: Reference = { // works here
    id: '1',
    type: 1
}

// INIT FROM DATA
interface Data {
    reference: {
        id: string,
        type: Category
    }
}

let data: Data = {
    reference: {
        id: '1',
        type: 1
    }
}

let reference_KO: Reference = { // <--- error occurs here
    id: data.reference.id,      // although the property is compatible
    type: data.reference.type   // yet the property is compatible
}

let param: Category = data.reference.type // == 1

let reference_KO2: Reference = { // <--- error occurs here
    id: data.reference.id,       // although the property is compatible
    type: param                  // yet the property is compatible
}

param = 1 // == data.reference.type - same variable

let reference_OK2: Reference = { // <--- no error happens here
    id: data.reference.id,
    type: param
}

You can explore this code in TypeScript playground

[update] I have included a scenario where a new reference is created from a variable (reference_KO2 - variable initialized from a property of data - and reference_OK2 - same variable initialized with a constant)

There are two different behaviors observed with the same variable of a compatible type!

Answer â„–1

Although the code may seem logically correct, the compiler will raise issues because the Data structure lacks specific information about the category underneath: it only recognizes that the field type belongs to a Category.

Therefore, we are faced with the dilemma that reference_ok can potentially be assigned as either a ReferenceOne or a ReferenceTwo. However, ReferenceOne mandates that type must belong to a CategoryOne, while ReferenceTwo requires type to align with a CategoryTwo. This becomes problematic since data.reference.type is categorized under a generic Category. To simplify and achieve the same outcome with less code, we deliberately "upcast" the value:

let r: Reference = {
  id: '1',
  type: 1 as Category,
}

To circumvent this issue, there are at least two possible approaches. One option involves redefining Reference as an interface to inform the compiler that the specific category need not be known during compilation:

interface Reference {
    id: string,
    type: Category,
}

A more favorable solution lies in utilizing generics. By enhancing Data to encompass the category type as well:

interface Data<C extends Category> {
    reference: {
        id: string,
        type: C
    }
}

With this modification, the following code functions smoothly:

let data: Data<CategoryOne> = {
    reference: {
        id: '1',
        type: 1
    }
}

let reference_KO: Reference = {
    id: data.reference.id,
    type: data.reference.type
}

A similar alteration could also be applied to Reference, if desired.

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

Problem with Clerk's authentication() functionality

Currently facing an issue with the Clerk auth() helper (auth() documentation) while working with react and next 13 (app router). When trying to access both userId and user from auth(), const { userId, user } = auth();, it seems that userId contains a val ...

Leverage the Node Short ID library in conjunction with Angular 6 using TypeScript

I attempted to utilize the node module within an Angular 6 typescript environment. Step one: npm i shortid Within my TypeScript class: import { shortid } from 'shortid'; let Uid = shortid.generate(); However, I encountered an error stating ...

How to update an Angular 2 component using a shared service

My question is regarding updating components in Angular 4. The layout of my page is as follows: Product Component Product Filter Component Product List Component I am looking to link the Product Filter and Product List components so that when a user c ...

Is the return type determined by the parameter type?

I need to create an interface that can handle different types of parameters from a third-party library, which will determine the return type. The return types could also be complex types or basic types like void or null. Here is a simple example demonstra ...

transferring libraries via functions in TypeScript

As I work on developing my app, I have decided to implement the dependency-injection pattern. In passing mongoose and config libraries as parameters, I encountered an issue with the config library. Specifically, when hovering over config.get('dbUri&ap ...

Ways to verify the identity of a user using an external authentication service

One of my microservices deals with user login and registration. Upon making a request to localhost:8080 with the body { "username": "test", "password":"test"}, I receive an authentication token like this: { "tok ...

I am interested in utilizing Vue Fallthrough attributes, but I specifically want them to be applied only to the input elements within the component and not on the container itself

I am facing an issue with my checkbox component. I want to utilize Fallthrough attributes to pass non-declared attributes to the input inside the checkbox component. However, when I add HTML attributes to the Vue component, those attributes are applied not ...

What is preventing me from applying styles to the first word in my Angular ngFor iteration?

I'm currently attempting to customize the initial word of a string within my Angular ngFor loop. Strangely, the class gets applied but the style defined in my CSS file is not. Inline styling also does not seem to work - any ideas why? This is the CSS ...

How to effectively filter a JSON array using multiple keys?

I need help filtering my JSON data by finding the objects with key 'status' equal to 'p' within the lease array. I attempted to use the following function, but it did not achieve the desired result: myActiveContractItems.filter((myActiv ...

How can TypeScript allow an argument to only accept keys that match another argument?

I'm currently developing a library that deals with linked lists. The current implementation is hardcoded to work with a list node type containing a "next" field that points to the next node of the same type. However, I am looking to make it more flexi ...

Managing state on the login page functions properly, although there is a minor inconvenience of having to click the login button twice after entering the username and password

In Login.tsx, I store user/pass info in a useState called login and pass it up to App.tsx. I then store the access property from login useState to access useState inside App.tsx. While this does technically work, there is an issue where it seems to be one ...

Broaden the scope of a `Record<string, string[]>` by adding a new type of property

When working in Typescript, it appears that defining the type as shown below should create the desired outcome: interface RecordX extends Record<string, string[]> { id: string } However, an error is thrown stating: Property 'id' of t ...

Access the global window variable from index.html within a Vue component

In my Vue project, I am incorporating an Stencil.js component in the following manner: index.html: <script type="module" src="https://xxxxxx.s3-eu-west-1.amazonaws.com/topbar.esm.js"> </script> <script> window.addEventLis ...

In Vue3, when using the `script setup` with the `withDefaults` option for a nested object, its attributes are marked as required. How can this issue

I have defined a props object with certain attributes: interface Props { formList: BaseSearchFormListItemType[], inline?: boolean searchBtn?: { show?: boolean text?: string type?: string size?: string } } const props = withDefaults( ...

Interacting between Angular Child and Parent components

I am facing an issue where I am trying to emit an event from a child component and display it in the parent HTML, but it doesn't seem to be working. Below is my code: ParentComponent.ts @Component({ selector: 'app-parent', templateUrl: ...

ElevationScroll expects the 'children' prop to be a single child component of type 'ReactElement<any, string>'

I am currently working on integrating the Elevate AppBar from Material UI into my application using the following code: interface Props { children: React.ReactElement; } export const ElevationScroll = ({children}: Props) => { const trigger = u ...

What is the best way to send a string parameter from an Angular UI to a Node.js backend?

My goal is to transfer a string value from an Angular UI to a Node.js backend API, which will then search in MongoDB using the provided string value as shown below. I am attempting to receive input in enteredValue and pass it on to the http.get call as pa ...

Leverage the child interface as a property interface containing a generic interface

I'm facing an issue while trying to incorporate typings in React. The concept is centered around having an enum (EBreakpoint) that correlates with each device we support. A proxy wrapper component accepts each device as a prop, and then processes the ...

NG0303: Unable to establish a connection with 'ngbTooltip' as it is not recognized as a valid property of 'button'

ERROR: 'NG0303: Can't bind to 'ngbTooltip' since it isn't a known property of 'button'.' Encountering this issue in my Angular 12 project when running local tests, the ngbTooltip error is present in all .spec files. ...

Could not find the 'injectTapEventPlugin' export in the dependencies of Material-UI related to 'react-tap-event-plugin'

Currently, I am working on a project that involves using react, typescript, material-ui, and webpack. An issue has arisen with importing the injectTapEventPlugin function from the dependency of Material-UI, react-tap-event-plugin. The specific error messag ...