Verifying callback type in Typescript based on another argument's validity

There is a JavaScript function that I am working with:

const fn = (cb, param) => {
  cb(param);
};

This function is meant to be called in two ways within TypeScript:

const cb0 = () => {};
fn(cb0);

const cb1 = (param: string) => { };
fn(cb1, 'str')

The expectations of the fn function are accurately described by this type:

interface IFn {
  (cb: (param: string) => void, param: string): void;
  (cb: () => void): void;
}

fnI(cb0); // ok
// fnI(cb1); // correctly does not compile, callback needs an argument
fnI(cb1, 's'); // ok

It checks types at the caller sites. However, I am facing issues converting fn to TypeScript without needing a type cast. Additionally, TypeScript seems to struggle with inferring argument types due to the overload declarations in IFn. The closest workaround I could come up with is:

const fn: IFn = <IFn>((cb: (param?: string) => void, param?: string) => {
  cb(param);
});

The issue arises when the implementation signature becomes less restrictive and violates the assertions defined in IFn, but TypeScript fails to detect this violation.

const fn: IFn = <IFn>((cb: (param?: string) => void, param?: string) => {
  cb(param === undefined ? 'some other string' : undefined);
});

Therefore, my question is: Is there a way to define the signature of fn or IFn so that TypeScript can catch violations within the implementation like the one mentioned above?

I want to address these issues without resorting to runtime checks.

Answer №1

Here is a suggestion to consider:

const myFunc = (
  ...args: [(param: string) => void, string] | [() => void]
) => {
  switch (args.length) {
    case 2: {
      const cb = args[0];
      const param = args[1];

      cb(param);
      break;
    }
    case 1: {
      const cb = args[0];

      cb();
      break;
    }
  }
};

Playground Link

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

The 'jsx' property in tsconfig.json being overridden by Next.js and TypeScript

Is there a way to prevent NextJS from changing the 'jsx' property in my tsconfig.json file from 'react' to 'preserve' when running the development server? This is how my tsconfig.json file looks: "compilerOptions": { " ...

Unwrapping nested objects in a JSON array with JavaScript: A step-by-step guide

After trying some code to flatten a JSON, I found that it flattened the entire object. However, my specific requirement is to only flatten the position property. Here is the JSON array I am working with: [{ amount:"1 teine med 110 mtr iletau" comment:"" ...

Typescript often fails to recognize that every code path within a function should return a value

Is it possible to inform TypeScript that all potential code paths in a function will return a value? In my scenario, I provide two numeric arrays as input, verify their monotonically increasing nature, and then retrieve a value based on specific condition ...

"Converting to Typescript resulted in the absence of a default export in the module

I converted the JavaScript code to TypeScript and encountered an issue: The module has no default export I tried importing using curly braces and exporting with module.exports, but neither solution worked. contactController.ts const contacts: String[ ...

Creating a React component with multiple prop types using Typescript

In this particular component, the requirement is to input a config object that can be of two types - either an object containing a "name" property (which should be a string), or a boolean value indicating that the config object has not been set yet. type C ...

Managing Visual Studio Code Extension Intellisense: A Guide

I am looking to create an extension I recommend using "CompletionList" for users. Users can trigger completion by running "editor.action.triggerSuggest" The process of my extensions is as follows: Users input text If they press the "completion command," ...

Tips for extracting year, month, and day from a date type in Typescript

I'm currently working with Angular 7 and I'm facing some challenges when it comes to extracting the year, month, and day from a Date type variable. Additionally, I am utilizing Bootstrap 4 in my project. Can anyone assist me with this? Below is ...

Is the translation pipe in Angular 5 impure?

I'm currently utilizing ngx-translate. Can you tell me if the translation pipe is considered pure or impure? Also, would it be more beneficial to use the directive syntax translate="X" instead? ...

Formatting Time in Angular 2 Using Typescript

Upon reviewing my date source, I found the following: TimeR ="2017-02-17 19:50:11 UTC"; Within the HTML file, I implemented this code snippet <span class="text-lg">{{TimeR | date: 'hh:mm'}}</span> The current output displays the t ...

Understanding NestJS Mixins and Their Distinction from Inheritance

After researching, I found that the Nestjs documentation does not include any information about mixins. Here is what I have gathered from my findings on Google and Stack Overflow: A mixin serves as a means of code sharing between classes within Nest. Esse ...

Troubleshooting Issue with Filtering Nested Object Array Based on Property

At the core of my data structure lies an array of orders, each containing an array of line items. These line items, in turn, are associated with their respective categories. I am currently attempting to filter the order array based on the category ID of th ...

Troubleshooting Angular 2: Why Array Interpolation is Failing

Greetings everyone, I am diving into Angular 2 and attempting to create a basic Todo application. Unfortunately, I've hit a roadblock. My array interpolation seems to be malfunctioning. Any assistance would be greatly appreciated. Here is my AppCompo ...

A method for transferring information stored in chrome.storage to a variable within an Angular component

How can I effectively assign data fetched from chrome.storage.sync.get to my Angular component's variable? Below is the code snippet of my component: export class KTableComponent implements OnInit { words: string[] = []; constructor() { } ...

What causes TypeScript to generate an error when using two array of object types, but not when using the shape of both?

There are two basic types of data available: type DataA = { percent: string; exchange: string; }; type DataB = { price: number; exchange: string; }; I'm puzzled as to why TypeScript gives errors when I try to use both types together: const ...

How can RxJS be used to handle only the first value returned when calling multiple URLs?

I am faced with the challenge of having multiple URLs containing crucial information. My goal is to find a specific ID within these URLs, but I do not know which URL holds the necessary details. The approach I'm taking involves calling each URL and us ...

Exploring the Potential of Jest Testing for Angular 6 Services

Hey there, I seem to be facing a bit of a roadblock and could use some assistance. Here's the situation - I'm trying to test a service using Jest, but all the tests pass without any issues even when they shouldn't. Here are the details of t ...

Invoking a parent method from a child component in a TypeScript and React application

I'm facing an issue where I am unable to call a method from a parent component in my child component. The method in the parent element is not being triggered when the child component tries to call it. This problem is showcased in a simple example with ...

Creating nested return types: A guide to defining function return types within a Typescript class

My large classes contain functions that return complex objects which I am looking to refactor. class BigClass { ... getReferenceInfo(word: string): { isInReferenceList:boolean, referenceLabels:string[] } { ... } } I am considering somethi ...

Looking for a regular expression to verify if the URL inputted is valid in TypeScript

After conducting thorough research, I discovered that none of the suggested URLs met my criteria, prompting me to raise a new query. Here are my specific requirements: * The URL may or may not include 'http' or 'https' * The URL can co ...

What could be causing the issue with my React Native app's release version not opening on a physical Android device?

I encountered an issue while trying to install the Release version of my application. In order to test both the debug and release versions on my physical and virtual devices, I utilized the following commands: ./gradlew assembleDebug, ./gradlew assembleRel ...