Typescript's handling of union and intersection types without errors in intersection scenarios

Trying to create a type that ensures an object has a type of A, B, or A and B. Despite my efforts, one of the cases I thought should fail is not failing. I suspect it's a silly mistake that I just can't seem to identify yet.

interface ValueSelector
{
    type: "id" | "value_string"
    value: string
}

interface TemporalSelector
{
    id: number
}

type Selector = (ValueSelector & TemporalSelector) || ValueSelector || TemporalSelector

// Should error
const e0: Selector = {}
const e1: Selector = { id: 0, value: "" }  // <-- does not error
const e2: Selector = { type: "id" }
const e3: Selector = { type: "value_string" }
const e4: Selector = { value: "" }
const e5: Selector = { value: "" }

// Should pass
const a1: Selector = { id: 0 }
const a2: Selector = { type: "id", value: "" }
const a3: Selector = { type: "value_string", value: "" }
const a4: Selector = { id: 0, type: "id", value: "" }
const a5: Selector = { id: 0, type: "value_string", value: "" }

Answer №1

e1 does not throw an error because { id: 0, value: "" } can be assigned to TemporalSelector since it only expects the id property.

If you want to fix this, you can utilize the StrictUnion helper:

interface ValueSelector {
    type: "id" | "value_string"
    value: string
}

interface TemporalSelector {
    id: number
}

type UnionKeys<T> = T extends T ? keyof T : never;
type StrictUnionHelper<T, TAll> = 
    T extends any 
    ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;

type StrictUnion<T> = StrictUnionHelper<T, T>


type Selector = (ValueSelector & TemporalSelector) | StrictUnion<ValueSelector | TemporalSelector>

// This scenario should produce an error
const e0: Selector = {}
const e1: Selector = { id: 0, value: "" }  // error
const e2: Selector = { type: "id" }
const e3: Selector = { type: "value_string" }
const e4: Selector = { value: "" }
const e5: Selector = { value: "" }

// These scenarios should pass without errors
const a1: Selector = { id: 0 }
const a2: Selector = { type: "id", value: "" }
const a3: Selector = { type: "value_string", value: "" }
const a4: Selector = { id: 0, type: "id", value: "" }
const a5: Selector = { id: 0, type: "value_string", value: "" }

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

Changing the font family for a single element in Next.js

One unique aspect of my project is its global font, however there is one element that randomly pulls font families from a hosted URL. For example: https://*****.com/file/fonts/Parnian.ttf My page operates as a client-side rendered application (CSR). So, ...

Navigating with Angular 6 using routerlink in a child module with router-outlet specified in the parent component (app.component

I'm currently working with the RouterModule and encountering an issue with the routerLinks. The problem I am facing is that the routerLinks are not functioning properly (the anchor tags are not clickable). This issue arises because they are located w ...

The JestImportMeta interface is mistakenly extending the ImportMeta interface, causing an error

While transitioning from jest version 27 to v29, I encountered this issue: node_modules/@jest/environment/build/index.d.ts:329:26 - error TS2430: Interface 'JestImportMeta' improperly extends interface 'ImportMeta'. The types returned ...

"Looking to access a model from a TypeScript file in Angular - here's how to

When my page loads, I am attempting to open a modal model. However, despite my efforts, the model does not open. I need to be able to trigger the click() event on the Launch demo modal button from ngInit() HTML <ng-template #content let-c="close&q ...

Killing the command prompt in Typescript: A step-by-step guide

Is there a way to completely close the cmd where the typescript file is running but unable to do so? How can this be achieved? console.log('This ts file must be terminate itself'); let asdef = process.pid; let asdeff = process.ppid; const {exe ...

What is the correct way to properly enter a Svelte component instance variable?

Currently, I am delving into learning Svelte and specifically exploring how to bind to a component instance as demonstrated in this tutorial: As I progress through the tutorial, I am attempting to convert it to Typescript. However, I have encountered an ...

What could be causing a Typescript-defined class property to unexpectedly appear as undefined?

My component has a property called options, which I have defined in the class. However, when I run the code in the browser, it's showing up as undefined. Despite thoroughly checking the code logic, I can't seem to pinpoint any issues. This could ...

TypeError: describe is not a function in the Mocha testing framework

Encountering an issue with mocha-typescript throwing an error indicating that describe is not defined. TypeError: mocha_typescript_1.describe is not a function at DatabaseTest.WrongPath (test/database_test.ts:21:9) at Context.<anonymous> ...

What is the best way to centralize JSDoc typedef information for easy sharing between different projects?

Currently, I am incorporating @typedef JSDoc comments at the beginning of my Javascript files to define types (primarily to access certain benefits of TypeScript without fully diving into it right now). I'm curious, where can I keep JSDoc typedef inf ...

Utilizing a Firebase function with Angular

I created the following function: retrieveLikedProperties(): AngularFirestoreCollection<any> { return this.afs.collection('users', ref => ref.where('uid', '==', this._auth.currentUserId) .where(&a ...

Watching - transforming / combining

I am a beginner when it comes to working with Observables. Here's the Effect that I am using: My goal is to dispatch the PositionUpdateAction or PositionFailedAction before the SunriseSunsetAction is dispatched. Currently, what happens is that the r ...

Troubleshooting Error in Angular 2 API: Issue with Reading Property "1" from Undefined

I have encountered an issue with my project as I am fetching data from an API on a server and trying to populate one of the objects with the retrieved data. However, the console is displaying an error stating that the Object is Undefined. Here is the erro ...

Close several dropdowns at once with ng-bootstrap

Within my Angular app, there are two dropdowns that I have integrated: <div class="input-group"> <input id="startDate" type="text" class="form-control" aria-label="Start date" ...

Navigating with Leaflet.PolylineMeasure in Angular app

The challenge I'm facing involves integrating the Leaflet.PolylineMeasure plugin into my Angular application, which is written in JavaScript. After attempting to npm install the library from https://www.npmjs.com/package/leaflet.polylinemeasure, I enc ...

SvgIcon is not a recognized element within the JSX syntax

Encountering a frustrating TypeScript error in an Electron React App, using MUI and MUI Icons. Although it's not halting the build process, I'm determined to resolve it as it's causing issues with defining props for icons. In a previous pro ...

Do I still need to install react-router if I have already installed @types/react-router?

My React project was initiated using create-react-app create-react-app my-app --scripts-version=react-scripts-ts Upon creation, the package.json file contained the following: { "name": "my-app", "version": "0.1.0", "private": true, "dependencies ...

Utilize zimJS within an Angular 4 application written in Typescript

After extensive searching, I have come up empty-handed in my quest to find the answer. There are no modules available for zimjs, only for createjs, but I require the entire package. I have exhausted all resources and still cannot find a solution. I am ke ...

How to effectively sort through users in Angular 6 without the need for a custom pipe

I am looking to customize the user.component template by implementing a filter functionality that will display only the users in the array that match the string entered in the text input field. Is there a way to bind the input value to the view without rel ...

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 ...

Can you explain the purpose of this TypeScript code snippet? It declares a variable testOptions that can only be assigned one of the values "Undecided," "Yes," or "No," with a default value of "Undecided."

const testOptions: "Undecided" | "Yes" | "No" = "Undecided"; Can you explain the significance of this code snippet in typescript? How would you classify the variable testOptions? Is testOptions considered an array, string, or another d ...