What method can be used to determine a number that is nonzero?

Defining the type of Result has presented some challenges for me. It should adhere to one of the following patterns:

type Result<Some> = { code: 0; some_result: ...}
// or
type Result = { code: NonZero; message: string}

How can I properly type this?

Perhaps, this question can be broken down into two parts:

  1. Developing NonZero (note that Exclude<number, 0> doesn't seem to work)
  2. Providing typings for the generic Result

Updates

I have crafted a functional snippet as shown below:

type Result<TCode extends number, T extends {} = {}> = TCode extends 0
  ? { code: 0; } & T
  : { code: TCode; reason: string };

type SomeResult = {some_result: string}

function getSomeResult(): Result<0 | -1 | 6007 | 114514, SomeResult> {
  return {
    code: 0,
    some_result: ''
  }
}

const result = getSomeResult()

switch (result.code) {
  case 0:
    // this is wrong: reason should be void
    result.reason
    // this is ok:
    result.some_result
    break
  default:
    // this is ok: there's always a reason when code is non-zero
    result.reason
}

Currently, the TS compiler is able to deduce that the other property defaults to void. Nonetheless, I am required to specify all potential non-zero values for code as a type parameter.

What's the best way to type NonZero?

Answer №1

It's impossible to input the keyword number without including zero, but this code snippet tries to closely mimic your syntax by introducing a cast to clarify the union type in the switch statement.

type Result<TCode extends number, T extends {} = {}> = TCode extends 0
  ? { code: 0; } & T
  : { code: TCode; reason: string };

type SomeResult = {some_result: string}

function getSomeResult(): Result<0, SomeResult> | Result<number> {
  if (Math.random()<0.5){
    return {
      code: 0,
      some_result: ''
    };
  }
  else {
    return {
      code: Math.floor(Math.random()+1),
      reason:""
    };
  }
}
function cast<T>(x:any): asserts x is T {}
const result = getSomeResult()
switch (result.code) {
  case 0:
    cast<Result<0,SomeResult>>(result);
    // this is incorrect: reason should be void
    result.reason
    // this is correct:
    result.some_result
    break
  default:
    cast<Result<number>>(result);
    // this is correct: there's always a reason when code is non-zero
    result.reason
}

typescript playground

A more conventional approach in TypeScript would involve adding a 'kind' field for clarification, thus eliminating the need for a cast.

type ResultNormal<T> = {
   kind: "normal";
} & T;
type ResultAbnormal = { 
   kind: "abnormal";
   code: TCode; reason: string 
};
function getSomeResult(): 
  ResultNormal<{some_result: string}> | ResultAbnormal {
  ...
}

This way, you can simply switch based on the 'kind' property.

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

Struggling to transfer RDS database instance metrics to a different stack

Within my development environment, I have two stacks in place - one dedicated to creating an RDS DB and the other focused on managing cloudwatch alarms. My goal is to pass the dbInstance details seamlessly between these two stacks: import * as cdk from &ap ...

The correct way to incorporate a global property into a component template (using Vue 3, Vite, TypeScript, and the Composition API)

The component's property is not functioning properly https://i.sstatic.net/qaUG9.png src/main.ts import { createApp } from 'vue' import languagePlugin from '@/plugins/languagePlugin' import App from './App.vue' const a ...

React-pdf has encountered a situation where more hooks were rendered compared to the last render cycle

I am currently integrating react-pdf to display a PDF document in a web view. The React application is built with TypeScript and Next.js. This is the code I have written so far: const MyPage: NextPage = () => { // some code here const [numPages, setN ...

How can CSS variables be applied to a hover property within an Angular directive?

Check out the directive below: import { Directive, ElementRef, HostListener } from '@angular/core'; @Directive({ selector: 'd-btn', host: {} }) export class ButtonDirective { constructor(private el: ElementRef){} @HostLis ...

Preparing a component for evaluation

When I execute the app and load views using @useview('resources/panels/data-table-panel.html'), everything works fine. However, running a component test results in failure due to a 404 error caused by the html file not being found. After changin ...

Guide on setting up @types from an NPM module containing the "@" symbol in its title

Installing the node package is easy npm install @gamestdio/timer --save But when attempting to add the corresponding types npm install @types/@gamestdio/timer --save An error occurs Invalid package name "@types/": name can only include URL-friendly ch ...

`Creating a union of prop types in TypeScript and React`

I'm facing an issue with a component prop that I need to restrict to specific strings using a union type, as shown below: type HeadingProps = { level?: 'h1' | 'h2' | 'h3' | 'h4'| 'h5' | 'h6&a ...

Utilizing proxies and leveraging the power of the Map collection in tandem

I have been exploring the Map collection and came across the [[MapData]] internal slot, which led me to utilize Reflect for trapping purposes. After some trial and error, I came up with the following code snippet: const map = new Map(); const proxiedMap ...

Having trouble locating the module for my custom TypeScript module

Exciting news! I have recently released a new TypeScript-based module on the NPM registry, called ooafs. However, when attempting to install and import it into another TypeScript project, an error pops up in VSCode stating: Cannot find module 'ooafs&a ...

Module augmentations do not allow for exports or export assignments

import { Request as ExpressRequest, Response as ExpressResponse } from 'express'; declare module 'kvl' { export = kvl; } declare const kvl: { ValidationDone:(param:(error: any, response: ExpressResponse) => void) => void; ...

What is the process for configuring the Authorization Header in ng2-signalr?

I am currently utilizing the library ng2-signalr within my ionic 2 project. I am facing an issue regarding setting the authorization header, as I have been unable to find any examples on how to do so. Below is my code snippet for establishing a connection ...

Next and previous buttons on Bootstrap carousel are not functioning properly with certain pop-up modals in a React application

Bootstrap Carousel Implementation for Viewing Photo Groups Utilizing a Bootstrap Carousel, I have created a feature to display different groups of photos. Each group of photos can be clicked on to open a Modal, showcasing all the images in a carousel form ...

The search is fruitless for a distinguishable entity '[object Object]' falling under the category of 'object'. In Angular 8, NgFor exclusively allows binding to Iterables like Arrays

My goal is to display a list of users using the ngFor directive. However, when I attempt to do this, the console displays an error message: Error ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object' ...

I'm unsure how to utilize the generic type in this particular scenario. It's a bit confusing to me

Recently, I delved into TypeScript generics and applied them in specific scenarios. However, I encountered some challenges. While working with two different interfaces, I faced a need for flexibility. For instance, I needed to make server requests. func ...

Encountering a TypeError while utilizing a custom hook for an Apollo mutation operation

I'm facing a tough time debugging an issue with my Apollo mutation in my NextJS application. The error I'm encountering is as follows: "TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))" It appears t ...

How can I prevent scrolling in Angular's cdk-virtual-scroll feature?

Is there a way to use Angular's cdk-virtual-scroll to prevent the scrollbar from moving by default? I have done extensive research but have not been able to find a solution. ...

What could be the reason behind the absence of this.props.onLayout in my React Native component?

In my React Native app, I have the below class implemented with Typescript: class Component1 extends React.Component<IntroProps, {}> { constructor(props){ super(props) console.log(props.onLayout) } ... } The documentation for the View ...

Unable to view loggly-winston debug logs on the user interface

I am having an issue where I cannot see any logs when calling winston.debug. It seems like the log level allowed to be seen needs to be changed. For more information, refer to the winston documentation or the Loggly node.js documentation. To start, instal ...

Error: Unable to locate namespace 'google' in TypeScript

I am currently working on an angular-cli project. ~root~/src/typings.json { "globalDevDependencies": { "angular-protractor": "registry:dt/angular-protractor#1.5.0+20160425143459", "jasmine": "registry:dt/jasmine#2.2.0+20160621224255", "sele ...

Utilizing a loaded variable containing data from an external API request within the useEffect() hook of a React component

Essentially, I have an API request within the useEffect() hook to fetch all "notebooks" before the page renders, allowing me to display them. useEffect(() => { getIdToken().then((idToken) => { const data = getAllNotebooks(idToken); ...