The Typescript code manages to compile despite the potential issue with the type

In my coding example, I have created a Try type to represent results. The Failure type encompasses all possible failures, with 'Incorrect' not being one of them. Despite this, I have included Incorrect as a potential Failure.

type Attempt<T, E> = Success<T> | Failures<E> | E;

// User code

type Failure = FileNotFound | NameNotFound;

class FileNotFound extends BaseFailure {}
class NameNotFound extends BaseFailure {}

class Incorrect extends BaseFailure {}

type Outcome<T> = Attempt<T, Failure>

function action() {
  let result = operation(1);
  if (result.isSuccess) {
  } else {
    result.hasMany;
  }
}

function operation(num:number): Outcome<String> {
  if (num > 3) {
    return new Success("Hello");
  } else {
    return new Incorrect();
  }
}

Answer №1

Typescript utilizes structural compatibility for determining type compatibility. When evaluating whether the class Incorrect is compatible with Failure, it compares the structure of Incorrect with the members of the Failure union. This analysis reveals that FileNotFound shares the same structure as Incorrect, making them compatible.

To address this issue, you can add a member (preferably private) to all classes in the union. For instance, the following code snippet demonstrates a scenario where failure occurs:

class Success<T> { constructor(public value: T) { } isSuccess: true = true }
type Try<T, E> = Success<T> | E;

class BaseFailure {
    isSuccess: false
}

type Failure = FileNotFound | NameNotFound;

class FileNotFound extends BaseFailure { private _type: "filenotfound" }
class NameNotFound extends BaseFailure { private _type: "namenotfound" }

class Incorrect extends BaseFailure { }

type Result<T> = Try<T, Failure>

function y() {
    let x1 = x(1);
    if (x1.isSuccess) {
    } else {
    }
}

function x(a: number): Result<String> {
    if (a > 3) {
        return new Success("Hallo");
    } else {
        return new Incorrect(); // error now
    }
}

You can also include the private field in BaseFailure to mandate implementers to specify it:

class BaseFailure<T> {
    isSuccess: false
    private __type: T
}


class FileNotFound extends BaseFailure<"filenotfound"> { }
class NameNotFound extends BaseFailure<"namenotfound"> { }

class Incorrect extends BaseFailure<"incorrect"> { }

The concept of allowing nominal typing has been a subject of ongoing discussion (refer to the issue). For now, implementing the aforementioned approach represents the most effective solution.

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

Tips on invoking Bootstrap's collapse function without using JQuery

We are facing a challenge with our TypeScript files as we have no access to jQuery from them. Our goal is to trigger Bootstrap's collapse method... $(object).collapse(method) but without relying on jQuery. Intended Outcome //Replicates the functio ...

Can you explain the meaning of this TypeScript code snippet?

interface Configuration { [input: string]: any; } This is really puzzling to me, the 'input' is declared as a string type with any value? Appreciate your help. ...

What is the importance of always catching errors in a Promise?

In my project, I have implemented the @typescript-eslint/no-floating-promises rule. This rule highlights code like this - functionReturningPromise() .then(retVal => doSomething(retVal)); The rule suggests adding a catch block for the Promise. While ...

Ensure that only numerical values in decimal form are permitted when entering data in Angular

How can I restrict user input to only decimal values? Here is the HTML code for my input field: <label for="conversion-factor">Conversion Factor:</label> <input type="text" class="form-control form-control-sm" id="conversion-factor" ...

Is there a way to establish a data type using a specific key within the Record<K, T> structure in Typescript?

Imagine the scenario where an object type needs to be created and linked to a specific key specified in Record<Keys, Type>. Let's say there is a type called User, which can have one of three values - user, admin, or moderator. A new type called ...

Retrieve the time zone setting from either my browser or server, and then incorporate it into angular2-highcharts

My current timezone setup is done manually using the timezoneOffset function from the Highcharts API. I am currently in GMT+2 so I set it to -2 * 60. However, I encountered an issue where my setup would not work properly when the hour changes in October. T ...

The listener for @ok is not being activated when using jest-test-utils with b-modal in vue-bootstrap

I have implemented the vue-bootstrap b-modal feature with the @ok="save" hook Here is a snippet of mycomponent.vue: <template> <div> <b-button @click="add">open modal</b-button> <b-modal static lazy id="modal-detail" ...

What is the best way to convert a `readonly string[]` to a regular `string[]`?

My data setup is as follows (I am not declaring it as an enum because it is used in both TypeScript server code and non-TypeScript client code): import { enumType } from 'nexus'; export const TYPE_ENUM = Object.freeze({ H: 'H', S: ...

Tips for sending props, state, or arguments to a TypeScript React component

Hey there, total newbie here... I'm currently working on a school project and I've hit a bit of a roadblock... I'm attempting to pass some props from one component to another, but for some reason, it's not working properly. The goal ...

Using Angular 4 to monitor changes in two-way binding properties

Recently, I developed a unique toggle-sorting component that examines if the current sorting parameters align with its sorting slug and manages clicks to reflect any changes. // toggle-sorting.component.ts @Input() sortingSlug: string; @Input() currSorti ...

Using Angular material to display a list of items inside a <mat-cell> element for searching

Can I use *ngFor inside a <mat-cell> in Angular? I want to add a new column in my Material table and keep it hidden, using it only for filtering purposes... My current table setup looks like this: <ng-container matColumnDef="email"> < ...

The addition of types/cors in Express Typescript causes my POSTMAN request to hang indefinitely

I am experiencing an issue with my React web app and Express TypeScript backend. Previously, my POST request was functioning well, but now it seems to hang indefinitely on Postman without returning any errors. issueController.ts import { RequestHandler } ...

I'm currently working on building a fresh window with Tauri 1.2, combining the powers of Rust, React, and Typescript. However, I've encountered a few

Utilizing Tauri's WindowBuilder in Rust, I attempted to create a new window. Despite successfully generating a blank window, I encountered challenges: The inability to display any content on the window The failure to close the window Being relativel ...

Vitek - Uncaught ReferenceError: Document Is Not Defined

Why am I encountering an error when trying to use File in my vitest code, even though I can typically use it anywhere else? How can I fix this issue? This is the content of my vite.config.ts. /// <reference types="vitest" /> import { defin ...

Tips on optimizing data processing for quicker display with ngFor

I am currently facing an issue with loading a JSON file containing 3500 data. The data appears very slowly on the view, causing the application to work sluggishly. Below is a snippet of the JSON: export class Service { private items = new Arr ...

What is the best way to extract values from a specific table column and store them in an array using Angular?

I have a section of code containing a table in my component: expect-next-month.component.html <table id="users"> <tr> <th>Number of month</th> <th>Total checking e ...

Validation of emails in Angular through the utilization of reactive forms

Hello there, I'm new to Angular and looking for some assistance. Specifically, I am currently working on validating an email input using a reactive form with the keyup event. registerform:any; ngOnInit(): void { this.registerform = new F ...

Show varying mat-options based on the selected value of another mat-select

When selecting a continent from the first mat-select, only the countries belonging to that continent should appear in the second mat-select options. For example, if Asia is chosen as the continent, only Asian countries should be displayed. <div class=&q ...

There seems to be an issue with the OpenAPI generator for Angular as it is not generating the multipart form data endpoint correctly. By default

Here is the endpoint that needs to be addressed: @PostMapping(value = "/file-upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public List<FileReference> handleFileUpload( @RequestPart(value = "file", name = "f ...

Creating a dynamic dropdown menu where the available options in one select box change based on the selection made in another

Looking at the Material-UI Stepper code, I have a requirement to create a select element with dynamic options based on the selected value in another select within the same React component. To achieve this, I wrote a switch function: function getGradeConte ...