Restricting enum type to only one member

enum Value {
    First,
    Second,
}

interface Data {
    value: Value
    number: number
}

interface SubData {
    value: Value.Second
}

function calculation(input: SubData){
    return;
}

function initiate(){
    const input : Data = {
        number: 100,
        value: Value.Second
    }

    if(input.value !== Value.Second) return;
    
    calculation(input)
                 // ^^^^ Types of property 'value' are incompatible.     
                 //      Type 'Value' is not assignable to type 'Value.Second'.
}

Playground

  1. If SubData and Data had the same fields, we could use a type predicate to narrow it down. But my problem requires that SubData will only have a subset of the fields of Data. Therefore a type predicate wouldn't work [playground].

  2. We could also change the type of value in the interface SubData to Value. And then move the if check for the second value inside calculation function. But let's also say I don't want to do that. I don't want to give the function this responsibility.

  3. We could create a new object of type SubData based on the original object and then pass that to calculation() instead. But this feels like a workaround (and extra code) because we couldn't narrow down the type [playground].

Is there a way to properly narrow down the type without breaking the rules? (no any or casting)

Answer №1

To determine whether the item is of type MetersMeasurement or Measurement, you can employ a method known as a type guard.

enum Unit {
    Kilometer,
    Meter,
}

interface Measurement {
    distanceUnit: Unit;
    distance: number;
}

interface MetersMeasurement {
    distanceUnit: Unit.Meter;
}

function someCalculation(item: MetersMeasurement){
    return;
}

function isMeasurement(obj: Measurement): obj is Measurement {
  return (obj as Measurement).distance !== undefined;
}

function main(){
    const item = {
        distance: 100,
        distanceUnit: Unit.Meter
    }

    if(isMeasurement(item)) return;
    
    someCalculation(item)
}

Answer №2

Give this a try:

enum Unit {
    Kilometer,
    Meter,
}

type Distance = {
    distance: number;
}

type MetersMeasurement = {
    distanceUnit: Unit.Meter;
} & Distance

type KilometersMeasurement = {
    distanceUnit: Unit.Kilometer;
} & Distance

type Measurement = MetersMeasurement | KilometersMeasurement;


/*
 * output is in kilometers
 */
function meterToKilometerConversion(item: MetersMeasurement) {
    return item.distance * .001;
}

function main(){
    const item : Measurement = {
        distance: 100,
        distanceUnit: Unit.Meter
    }

    if (item.distanceUnit == Unit.Meter) {
        meterToKilometerConversion(item);
    }
}

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

Can you verify that the client's date and time locale are accurate in JavaScript before proceeding with processing?

For my application, I am seeking the current locale datetime. However, before retrieving the date, it is crucial to verify that the local date and time are accurate. If the user has adjusted the date and time incorrectly on their machine, I must prompt a ...

What is the proper way to utilize useRef in TypeScript to assign a function to ref?

I am just diving into Typescript and I am looking to assign a function to a ref within a custom hook. My goal is for the function to remain constant throughout renders. Check out the code on CodeSandbox: https://codesandbox.io/s/918l0wro4r function runFu ...

React Native Async Storage: displaying a blank page issue

I am facing an issue while attempting to save my data locally using AsyncStorage, specifically with the getData method. const storeData = async (value: string) => { //storing data to local storage of the device try { await AsyncStorage.setItem(& ...

The parameter type 'Event' cannot be assigned to the argument type

edit-category-component.html: <custom-form-category *ngIf="model" [model]="model" (onSaveChanges)="handleChanges($event)"></custom-form-category> <mat-loader *ngIf="!model"></mat-loader> edi ...

Even though there is data stored in the array, the React Native array.length appears to be returning a value

I am struggling with what appears to be a simple issue, and it's frustrating that I've had to seek help for this. The problem lies in iterating through an array messages: Message[] = [...]. No matter what method of iteration I try, it doesn&apos ...

What is the method to invoke a function within another function in Angular 9?

Illustration ` function1(){ ------- main function execution function2(){ ------child function execution } } ` I must invoke function2 in TypeScript ...

"Implementing a retry feature for Angular http requests triggered by a button

Imagine having a situation where a component has a method that triggers an http request defined in a service. The observable is subscribed to within the component: Component: fetchData() { this.apiService.fetchDataFromServer().subscribe( respo ...

Node Package Manager (NPM): Easily Importing Files from a Package

Is there a way to customize the file import paths within a package? I am working with a UI kit package for our internal project and after building with Webpack, my project structure looks like this: - dist - components - index.d.ts - index.js Prior ...

Automatically closing the AppDateTimePicker modal in Vuexy theme after selecting a date

I am currently developing a Vue.js application using the Vuexy theme. One issue I have encountered is with a datetimepicker within a modal. The problem arises when I try to select a date on the datetimepicker component - it closes the modal instead of stay ...

The view fails to update when the object is modified

Within the acceptRequest function in child.component, the commissioner.requestAccepted property is set to false, and then the updated commissioner object is returned. Ideally, I want the button to be automatically removed from the view once the object is ...

How can I programmatically trigger the optionSelected event in Angular Material's autocomplete?

I'm currently facing an issue with my Angular Autocomplete component. I am trying to trigger the (optionSelected) event within the ts file after a different event by setting the input with the updated option using this.myControl.setValue(options[1].va ...

Automating the linking of tsd definitions with bower and npm: A step-by-step guide

Currently, I am in the process of transitioning an existing project to TypeScript which includes numerous bower and npm dependencies (bower.json and package.json). As mentioned on the tsd github page, TSD facilitates the discovery and linking of defini ...

An unexpected error occurs when attempting to invoke the arrow function of a child class within an abstract parent class in Typescript

Here is a snippet of code that I'm working on. In my child class, I need to use an arrow function called hello(). When I try calling the.greeting() in the parent class constructor, I encounter an error: index.ts:29 Uncaught TypeError: this.hello is ...

What is the syntax for assigning a public variable within a TypeScript function?

I am finding it challenging to assign a value to a public variable within another function. I seem to be stuck. export class MyClass{ myVar = false; myFunction(){ Module.anotherFunction(){ this.myVar = true; } } } ...

When calling UIComponent.getRouterFor, a TypeScript error is displayed indicating the unsafe return of a value typed as 'any'

I have recently integrated TypeScript into my SAPUI5 project and am encountering issues with the ESLint messages related to types. Consider this simple example: In this snippet of code, I am getting an error message saying "Unsafe return of an any typed ...

Issue with updating Angular list reference when deleting an item

My current task involves implementing a feature that displays selected items from a hierarchical structure on the right side. slice.component.ts : import { Component, Input, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core&a ...

Guide to implementing an enum in an Angular Component

Having a global state (or "mode") in my Angular Components is leading me to look for more efficient ways to code. Here is what I have tried: @Component({ .... }) export class AbcComponent implements OnInit { enum State { init, view, edit, cre ...

TS2304 error: 'Promise' is nowhere to be found

Hey everyone, I've exhausted all the solutions available on stackoverflow with no luck. So here's my question. tsconfig.json { "version":"2.13.0", "compilerOptions": { "target": "es5", "module": "commonjs", "sourceMap": true, ...

I encountered some problems with conflicting Angular dependencies, so I decided to delete the node_modules folder

An error has occurred: The module 'H:\All_Files\Scripts\Angular\example\node_modules\source-map\source-map.js' could not be found. Please ensure that the package.json file contains a correct "main" entry. ...

Using the Ngclass function with a pair of objects

Can you include 2 objects in an ngclass function like this? <div class="progress-bar"[ngClass]="getProgressValues(obj.val1,obj.val2)"> </div> I am encountering a JSON error. SyntaxError: JSON.parse: bad control character in string literal at l ...