Typescript: Conflicts between property names in types and interfaces

Consider a scenario where there are 2 types with the same property name but different data types:

type A = {
  myProperty:string
}

type B = {
  myProperty:number
}

If both types are extended using an interface, an error is expected:

interface C extends A, B {}
Interface 'C' cannot simultaneously extend types 'A' and 'B'.
  Named property 'myProperty' of types 'A' and 'B' are not identical.

However, when a type is used to extend both types, no exception occurs. In this case, what will be the resulting data type of myProperty? Is there a method to verify the resulting data type?

type C = A & B; // no error

If C is declared as a type, it is not possible to assign a value (string or number) to myProperty. How can this situation be best managed?

function F(myParameter:C) {
  console.log(myParameter);
}

F({myProperty: 90});
(property) myProperty: never
Type 'number' is not assignable to type 'never'.ts(2322)
index.ts(3, 3): The expected type comes from property 'myProperty' which is declared here on type 'C'

The same error occurs if the function is called as F({myProperty: 'test data'});.

Interactive example: https://codesandbox.io/s/typescript-playground-export-forked-dglbq5?file=/index.ts

Answer №1

If you're looking to merge two conflicting types while still being able to create the resulting type, there are several approaches you can take. Keep in mind that these solutions won't resolve conflicts for properties nested more than one level deep.

Consider having two interfaces, A and B, that we want to intersect:

interface A {
    a: string
    b: string
}

interface B {
    a: number
    c: string
}

One option is to exclude the conflicting property from the final type:

type IntersectByOmitting<A, B> = {
    [K in keyof (A & B) as K extends keyof A & keyof B 
      ? [A[K] & B[K]] extends [never] 
        ? never 
        : K 
      : K
    ]: K extends keyof A ? A[K] : B[K & keyof B]
}

type T0 = IntersectByOmitting<A, B>
//   ^? type T0 = { b: string; c: string; }

In this case, since 'a' results in 'never' in the intersection, it will be left out of the final type.


Alternatively, you may prefer to have a union of the conflicting properties:

type IntersectByUnion<A, B> = {
    [K in keyof (A & B)]: K extends (keyof A & keyof B) ? 
      [A[K] & B[K]] extends [never] 
        ? A[K] | B[K] 
        : A[K] & B[K]
      : K extends keyof A ? A[K] : B[K & keyof B]
}

type T1 = IntersectByUnion<A, B>
// type T1 = {
//    a: string | number;
//    b: string;
//    c: string;
// }

Now, the type of 'a' becomes 'string | number'.

Playground

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

Using ngFor in Angular with an array consisting of nested arrays

List item: jsonObject = [ { place: 'place1', fatherDetails: [ {name: 'place1_father1', adharId: 134567}, {name: 'place1_father2', adharId: 124567}, ], motherDetails: [ {nam ...

Performing an insertion in TypeORM with a foreign key connection

In my database schema, I have set up a relationship where each Chatroom can have multiple Messages linked to it. However, when I try to insert a Message (or a batch of Messages), the foreign key for ChatRoom is not being assigned properly and remains null. ...

Receiving an error when trying to import the 'marked' module into an Angular project

Working on a project with Angular 15, I recently added marked to transform MarkDown text to HTML using an Angular pipe. However, no matter how I import it, I can't seem to get it working and keep encountering errors. I followed these steps: npm i mar ...

Convert a collection of observables containing events to an observable array of events

I am working on creating a function that merges all event streams generated from an array of data channels and emits any event received from them. Below is the initial function: private dataChannels: BehaviorSubject<RTCDataChannel[]> = new Behavi ...

Implementing Batch File Uploads using Typescript

Is there a way to upload multiple files in TypeScript without using React or Angular, but by utilizing an interface and getter and setter in a class? So far I have this for single file upload: <input name="myfile" type="file" multi ...

Transforming an object's type into an array of different types

Looking to create an array of types based on object properties: type T = { a: number | string; b: string | number; c: number; d: boolean; }; Desired Output: [number | string, string | number, number, boolean] Intending to use this as a ...

Universal - Permissible data types for function and constructor arguments

In many statically typed languages, it is common to specify a single type for a function or constructor parameter. For example: function greet(name: string) { ... } greet("Alice") // works greet(42) // error TypeScript is an extension of JavaScri ...

Differences between `typings install` and `@types` installation

Currently, I am in the process of learning how to integrate Angular into an MVC web server. For guidance, I am referring to this tutorial: After some research and noticing a warning from npm, I learned that typings install is no longer used. Instead, it ...

Leveraging Global Variables for Validation in Angular (Angular 10)

I am currently creating a form in Angular 10 which involves the use of validators. Specifically, I have been utilizing the Validators.min() method within my form... Instead of manually inputting the value '100' in the Validators.min('100&ap ...

The function using the React Hook "useState" is not a React function in TypeScript

Issue arises when attempting to use the useState hook within my component. While I can successfully define props on both Container and Continer.Element, encountering errors when trying to invoke Hooks inside Container.Element. const Container: React.FC&l ...

The Typescript errors is reporting an issue with implementing the interface because the type 'Subject<boolean>' is not compatible with 'Subject<boolean>'

Creating an Angular 2 and Typescript application. I am facing an issue with an abstract class within an NPM package that I am trying to implement in my app code. Everything was functioning correctly until I introduced the public isLoggedIn:Subject<bool ...

Identify the type of a characteristic based on the discriminant for the associated member of a discriminated union

In this discriminated union, the property id is assigned a different type based on the discriminant value: type TableKind = 'administration' | 'data' type AdministrationTableId = 'Modules' | 'Users' | 'Roles&ap ...

Restricting array elements through union types in TypeScript

Imagine a scenario where we have an event type defined as follows: interface Event { type: 'a' | 'b' | 'c'; value: string; } interface App { elements: Event[]; } Now, consider the following code snippet: const app: App ...

Troubleshooting issues with sorting and pagination in Angular Material table functionality

I am experiencing an issue with sorting and pagination using an Angular material table. The data is being fetched from a store as an observable and successfully displayed in the table. Even though the column names for sorting match the column definitions, ...

Example of TypeScript Ambient Namespace Usage

The Namespaces chapter provides an example involving D3.d.ts that I find puzzling. Here is the complete example: declare namespace D3 { export interface Selectors { select: { (selector: string): Selection; (element: ...

In TypeScript, the type of the second function parameter depends on the type of the first

I'm new to typescript programming. Overview In my typescript react application, I encountered an issue where I needed to dynamically watch the values returned from the watch() method in react-hook-form, based on different parameters passed into a cus ...

Receiving an error when triggering an onclick event for a checkbox in TypeScript

I am creating checkboxes within a table using TypeScript with the following code: generateTable(): void { var table = document.getElementById("table1") as HTMLTableElement; if (table.childElementCount == 2) { for (var x = 0; x < 2; x++) ...

Registering a function for chart.js plugins that manipulates external data

Is there a way to pass external data to the chart.plugins.register function? I'm struggling because I can't access the necessary context: Chart.plugins.register( { beforeDraw: function (chart) { //implementation } }); I attempted using ...

What is the best way to ensure the flat list only renders once?

My objective is to display the ComponentTwo Flatlist just once, however, I am currently seeing the output as shown in image1, whereas I want it to be displayed like in image2. To showcase this issue, I have included a snack link containing the relevant cod ...

What is the best way to insert CSS code into a custom Vue directive file?

I need a solution that applies a gradient background to the parent div in case an image fails to load. I've attempted to create a directive for this purpose: export default { bind(el: any, binding: any) { try { ..... ...