Is it false that 0 | "", 2 | {} extends 0 | "", and 0 ? true : false returns false?

0 | "" | {} extends 0 | ""  // false
0 | "" | {} extends 0 | {} // true

Comparing the union 0 | "" | {} to 0 | "", it seems like the former technically extends from the latter. However, I am puzzled by the fact that it returns false.

This query arose from a Typescript type-challenge solution for AnyOf. It would be really helpful if someone could break down how Typescript determines whether UnionA extends UnionB is true or false.

Answer №1

The keyword ES6 classes is used to illustrate the concept of specialization:

class SubClass extends BaseClass...
. This indicates that SubClass is a more specialized type.

However, a problem arises when considering
0 | "" | {} versus 0 | "". Instead of narrowing down the possibilities, adding {} expands the options, making false the correct return value.

To test the idea of "MoreSpecific extends LessSpecific", consider:

0 | "" extends 0 | "" | {} ? true : false
(result: true).

Another perspective involves assignments.

let variable: BaseClass = some_instance_of_SubClass
should be valid. But trying
let myVar1: 0 | "" = value;
fails because none of the union type members permit assigning {}.

In the case of

0 | "" | {} extends 0 | {}
, peculiarities of the empty object type are at play. Various assignments can be made:

let test1: {} = ""
let test2: {} = 34
let test3: {} = {"anything you like": "other than null or undefined"}

(historically for compatibility, see https://github.com/microsoft/TypeScript/issues/44520 “It's a concession to back-compat because { } was the top type when generics were introduced”)

Since anything other than null or undefined can be assigned to {}, it follows that 0 | "" | {} is assignable to {} and consequently to 0 | {}. Therefore, the statement ""... extends ..."" holds true.

The inclusion of "" as an 'extra possibility' is encompassed within the {} part of 0 | {}.

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

Enhance your text in TextInput by incorporating newline characters with advanced editing features

I'm encountering an issue with my Textarea component that handles Markdown headers: type TextareaProps = { initValue: string; style?: StyleProp<TextStyle>; onChange?: (value: string) => void; }; type OnChangeFun = NativeSynthetic ...

Tips for effectively handling projects that call for varying versions of TypeScript within Visual Studio

In some cases, developers have had to downgrade their TypeScript version in order for it to work with a specific npm package version. Is it possible to do this with Visual Studio? I recently obtained a sample solution that utilized the angular2 npm packag ...

Encountering an error in Angular 8 with the plugin: Unhandled ReferenceError for SystemJS

I recently followed a tutorial on integrating plugins into my Angular application at this link. I'm trying to create a component in my Angular app that can execute and display an external component. However, I encountered the following error: Uncaugh ...

Utilizing the Node.js `cluster` module in TypeScript/CommonJS with DT @types/[email protected]

I am currently managing a TypeScript application using Node's cluster API that was successfully built with Node 14.x and the cluster types from DT. Upon transitioning this application to Node 16.x, I updated the @types/node package from version 14.x ...

Learning to access $refs values in Vue.js

In my Vuejs (3) project that uses Typescript, I am working on avoiding the use of the type any with $refs: const el = (this.$refs['target'] as any).$el This results in a warning message: warning Unexpected any. Specify a different type @typesc ...

Steps for adjusting the status of an interface key to required or optional in a dynamic manner

Imagine a scenario where there is a predefined type: interface Test { foo: number; bar?: { name: string; }; } const obj: Test; // The property 'bar' in the object 'obj' is currently optional Now consider a situatio ...

Error in Typescript with a Bluebird library: The 'this' context is not compatible with the method's 'this' context

I have a collection of methods (some synchronous and some asynchronous) that I wish to process sequentially using bluebird.each. Here's a simplified example: import bluebird from 'bluebird'; const delay = (ms: number) => new Promise((res ...

Variable type linked to interface content type

Is it possible to link two fields of an interface together? I have the following interface: export interface IContractKpi { type: 'shipmentVolumes' | 'transitTime' | 'invoices'; visible: boolean; content: IKpiContent; } ...

Tips for testing and verifying the call to a specific Firebase method within a function using Jest

Within the file App.ts, I am utilizing the method firebase.auth().signInWithEmailAndPassword(email, password). Now, my objective is to conduct a unit test to ensure that when the myAuthenticationPlugin.authenticate(email, password) method is invoked from ...

The Angular RXJS HTTPClient fails to properly handle HttpErrorResponses

In my Angular 12 project, I am facing an issue with setting up unit tests that should capture errors from HTTP responses. However, when running the tests, instead of receiving the error as an actual error object, it is being passed within the response body ...

Error: The 'trimLeft' property is not found on the 'string' type. Libraries included: ["dom", "es2018"]

When I run the code below, I encounter this Error: let foo = ' foo ' console.log(foo.trimLeft()) //foo.trimStart() works neither I've noticed that many online solutions suggest editing my tsconfig.json to include es20whatever. What&apos ...

Guide to transforming JSON data into a different structure

My API is currently providing data in this format: [ { "lattitude": 52.57812538272844, "longitude": -1.7111388218750108, }, { "lattitude": 53.043884, "longitude": -2.923782, } ] I need to transform the data ...

Strategies for effectively searching and filtering nested arrays

I'm facing a challenge with filtering an array of objects based on a nested property and a search term. Here is a sample array: let items = [ { category: 15, label: "Components", value: "a614741f-7d4b-4b33-91b7-89a0ef96a0 ...

typescript extending a type from a higher-level interface

Consider the TypeScript interface provided below: export interface Update { type: 'STATUS_UPDATE'; } I am interested in extending this interface by adding one more value to the type property, as shown here: export interface HttpUpdate extends ...

Tips on how to reach an Angular component within a third-party library

I'm currently working on a web application that incorporates the Deezer player through the official JS SDK. I've run into an issue where I am unable to access my Angular component from within the Deezer event subscription. The arrow function does ...

What is the best way to obtain an authentic 16-bit value?

Currently, I am working with an LPC1768 using the mbed interface. Take a look at this code snippet: int16_t test = -1; test -= 1; printf("Value: %d\n", sizeof(test)); if (test == 0xFFFE) { printf("It's stayed the same.\n"); } else if ( ...

Is there a way to enforce a mandatory lambda argument?

I am trying to pass a lambda into a function, but I need the lambda to have only one argument. TypeScript correctly generates an error if I provide two parameters to the lambda, however it does not raise any issues if I leave out any arguments altogether ...

Angular (TypeScript) time format in the AM and PM style

Need help formatting time in 12-hour AM PM format for a subscription form. The Date and Time are crucial for scheduling purposes. How can I achieve the desired 12-hour AM PM time display? private weekday = ['Sunday', 'Monday', &apos ...

Looking to troubleshoot an error in my TypeScript reducer implementation. How can I fix this issue?

I'm currently using typescript along with react, redux, and typessafe-actions. However, I've come across a particular error that I need help with. The error message reads: "No overload matches this call. Overload 1 of 2, '(...items: Concat ...

In Angular 14, it is crucial to remember that RxJS can only subscribe once within a single component. It is not possible to have

When using Rxjs in Angular 14, it's important to note that subscription occurs only once in a single component, not across different components simultaneously. Project Description I am currently developing a notification service for my application. ...