What is the rationale behind allowing conflicting types in intersection types?

When presented with two interfaces containing conflicting member types:

interface A { x: number }
interface B { x: string }

It becomes impossible to create an interface that extends both:

interface I extends A, B
// error TS2320: Interface 'I' cannot simultaneously extend types 'A' and 'B'.
// Named property 'x' of types 'A' and 'B' are not identical.

However, it is viable to define an intersection type that integrates A and B:

let c = A & B
type C = A & B 
// no type errors

Even though, this type cannot be instantiated:

let withNumber: C = { x: 10 }
error TS2322: Type '{ x: number; }' is not assignable to type 'A & B'.
Type '{ x: number; }' is not assignable to type 'B'.
Types of property 'x' are incompatible.
Type 'number' is not assignable to type 'string'.

let withString: C = { x: "foo" }
// The same type error, with `number` and `string` reversed

The reason why intersection types do not flag conflicts upon definition remains unclear technically.

Answer №1

type operands may be type parameters; interface... extends operands must be definite types.

This difference allows type to have more flexibility than interface (this is essentially the reason behind type).

An implication of this is that the type operator cannot predict its entire set of member types in advance, so conflicts like the example mentioned are hard to detect.

In the words of Anders Hejlsberg,

The ability for operands to be type parameters greatly impacts the potential semantics of the operator. In essence, the operator must consistently function for any two operands with an unknown set of members as it's not feasible to identify errors during type instantiation (i.e. when actual types replace type parameters). This is what leads to the distinctions between & and extends. Since the real types are always known with extends, we can conduct more thorough checks and disallow constructs we consider incorrect from a traditional OOP perspective. For instance, we can flag an error when properties of conflicting types but the same name arise with extends, while we combine (intersect) their types with &.

For further details, refer to a similar query on Github and the intersection types pull request.

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

Contrast between categories and namespaces in TypeScript

Can you clarify the distinction between classes and namespaces in TypeScript? I understand that creating a class with static methods allows for accessing them without instantiating the class, which seems to align with the purpose of namespaces. I am aware ...

Fullcalendar in Angular fails to update events automatically

I am exploring the integration of fullcalendar with angular. Despite adding valid events to my events field, they are not displaying in the UI. However, hardcoded events are appearing. I am relatively new to angular, so the issue may not be directly relat ...

Displaying user input data in a separate component post form submission within Angular

I recently developed an employee center app with both form and details views. After submitting the form, the data entered should be displayed in the details view. To facilitate this data transfer, I created an EmployeeService to connect the form and detail ...

Tally up identical words without considering differences in capitalization or extra spaces

Let's take an example with different variations of the word "themselves" like "themselves", "Themselves", or " THEMSelveS " (notice the leading and trailing spaces), all should be considered as one count for themselves: 3 ...

Storing redux dispatch action using the useRef hook in Typescript

Currently, I am attempting to store the redux action dispatch in a React reference using useRef. My goal is to be able to utilize it for aborting actions when a specific button is clicked. Unfortunately, I am facing challenges with assigning the correct ty ...

Using Angular2, assign a value to the session and retrieve a value from the session

I am having trouble getting and setting a session. Here is my code: login_btnClick() { var NTLoginID = ((document.getElementById("NTLoginID") as HTMLInputElement).value); this._homeService.get(Global.BASE_USER_ENDPOINT + '/EmployeeDe ...

What steps should I take to successfully compile my Typescript Webpack project without any errors?

Currently, I am attempting to convert only two .js files into .ts files within my webpack node.js project and then compile them (actions.ts and flux.ts). When I execute the command: webpack --progress --colors I encounter the following errors: 'use ...

Issue regarding retrieving the image using TypeScript from an external API

Hey developers! I'm facing an issue with importing images from an external API. I used the tag: <img src = {photos [0] .src} /> but it doesn't seem to recognize the .src property. Can anyone shed some light on how this is supposed to work? ...

Having trouble connecting useRef eventListeners in TypeScript/JavaScript

Trying to connect an eventListener to a container in Typescript using useRef and useEffect hooks. The issue we are encountering is: No overload matches this call. Overload 1 of 2, '(type: keyof HTMLElementEventMap, listener: (this: HTMLDivElement, ev: ...

Typedoc does not create documentation for modules that are imported

Whenever I generate documentation with TypeDoc, I am encountering an issue where imported files come up empty. If I add a class to the file specified in entryPoints, I get documentation for that specific class. However, the imported files show no document ...

Send Components to another component without specific TypeScript typespecified

Struggling with a situation where I am faced with the challenge of working around strongly typed variables. The issue arises with a set of icons as components and an icon wrapper component. The wrapper component requires a themeMode variable to determine ...

Error: The function $compile does not exist

Currently, I am working on developing an AngularJS directive using TypeScript. While testing my code in the browser, I encountered the following error: TypeError: $compile is not a function at compileComponent.js:14 Interestingly, the TypeScript compiler ...

React TypeScript: Handling OnChange Events for Different Input Types

I am confronted with multiple input fields: <label> <span className="codes__input-label">Count</span> <input type="number" value={this.state.count} onChange={this.onInputChange} /> </label> ...

Why is it necessary for the required type of a function parameter to be able to be assigned to

From Optional to Required Type const testFunc = (func: (param: number) => void): void => { func(3); }; testFunc((a?: number) => { console.log(a); }); From Required to Optional Type const testFunc = (func?: (param: number) => void): void = ...

The functionality of verifying the type of an item in a list using Typescript is not functioning

In my TypeScript code, I am working with a type called NameValue and another one called MixedStuff. type NameValue = { name: string; value: string }; type MixedStuff = NameValue | string; function stripTwoChars(stuffs: MixedStuff[]): string { let st ...

Angular mouseenter event delay not functioning after initial trigger

Currently, I am attempting to create a delay for the mouseenter event when the user hovers over a div. The goal is for the video to start playing only after the user has hovered for at least 1 second. Initially, everything works as expected, but after the ...

"Error occurs as a result of an unspecified attribute in the map

Hello, I am currently traversing a tree structure recursively. To handle undefined nodes in the tree, I have implemented guards to prevent any failures. However, during the mapping of children nodes, I encountered the following error: Error Output Adri ...

Steps for integrating Cordova-vk plugin into an Ionic 3 project

I am looking to incorporate the cordova-vk plugin into my app, but I am having trouble connecting it to Typescript. vkSdk is not defined I understand that the plugin is located in the node_modules folder. How can I successfully integrate it into my page ...

Assembly of Components

As someone new to angular, I am currently in the process of building an angular2 application. My goal is to dynamically create a series of DOM components using the data provided below: // Class construct with properties sorted alphabetically export class ...

Angular 2's abstract component functionality

What are the benefits of utilizing abstract components in Angular 2? For example, consider the following code snippet: export abstract class TabComponent implements OnInit, OnDestroy {...} ...