How to create a Typescript function with a void return type that accepts any arguments

I am trying to create a decorator function that takes another function as an argument:

type SomeType = ??? => void;

const decorate = (fn: SomeType): SomeType => {
   ...
} 

How can I define the "SomeType" type in a way that restricts the decorate function to only accept functions with a return type of void?

const f1 = decorate((a: number) => {console.log(a);});   //OK
const f2 = decorate((a: number, b: string) => {console.log(a,b);}); //OK
const f3 = decorate((a: number, b: number) => {console.log(a,b); return a+b;});  //Not allowed

Answer №1

Breaking down the issue into two parts is essential. The first part involves maintaining argument types using the decorate function, while the second part focuses on ensuring the return type of the decorated function is void.

To address the first part, introducing a generic argument to the decorate function can help in capturing the actual arguments passed:

const decorate = <A extends any[]>(fn: (...a: A) => void): (...a: A) => void => {
   return fn;
} 

const f1 = decorate((a: number) => {console.log(a);});   //(a: number) => void;
const f2 = decorate((a: number, b: string) => {console.log(a,b);}); //(a: number, b: string) => void;
const f4 = decorate((a: number, b: number) => {console.log(a,b); return a+b;}); //(a: number, b: number) => void;

Playground Link

The second part presents a challenge, as the presence of void in a signature does not guarantee that the function will not return a value but rather that the return value will go unnoticed by the caller. While there are safeguards against explicitly returning a value with void, functions that return values can still be assigned to signatures requiring void.

function x() { return 1 }
let y : () => void = x

Playground Link

However, in scenarios where the return type must strictly be void within another function like the decorate function, leveraging conditional types can enforce custom error handling:

const decorate = <A extends any[], R>(fn: ((...a: A) => R & (void extends R ? unknown : ["Void required allowed"]))): (...a: A) => void => {
   return fn;
} 

const f1 = decorate((a: number) => {console.log(a);});   //OK
const f2 = decorate((a: number, b: string) => {console.log(a,b);}); //OK
const f3 = decorate((a: number, b: number) => {console.log(a,b); return a+b;}); //    Type 'number' is not assignable to type '["Void required allowed"]'.

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

Dealing with React and Firebase Authentication Errors: How to Handle Errors for Existing Accounts with Different Credentials

According to the documentation at https://firebase.google.com/docs/auth/web/google-signin#expandable-1, when error.code === 'auth/account-exists-with-different-credential', signInWithPopup() should return an error.email. However, in my specific c ...

Search timeout restriction

I have a function that makes a request to the server to retrieve data. Here is the code for it: export default class StatusChecker { constructor() { if (gon.search && gon.search.searched) { this.final_load(); } else { this.make_req ...

What happens when a CSS module is exported as an empty object?

My go-to for creating projects is using TypeScript and create-react-app. I recently incorporated the typings-for-css-modules-loader and dabbled in css-modules as well. { test: /\.css$/, use: [ require.resolve('style-loader'), { ...

JavaScript: Employ array destructuring for improved code readability (eslintprefer-destructuring)

How can I resolve the ESLint error that says "Use array destructuring. eslint(prefer-destructuring)"? The error occurs on this line of my code: let foo = 1; foo = obj.data[i][1]; //ESLint error on this line If anyone could provide assistance in fixing thi ...

Having trouble with Nextjs API Integration - encountering error 404

I'm currently facing a major issue and I've hit a dead end. I've been spending days trying to connect my local nextjs 14 app to the CVENT API, but I keep receiving a persistent 404 error. Here's what is displayed in the frontend console ...

Guide on creating an interface for a JSON object with an array of custom functions

I am working on developing an interface for a JSON object that consists of n keys with unknown names, each containing an array of functions with specific signatures. // CLASSES class Server { // Private variables mapping : IMapping = {} // ...

Consistentize Column Titles in Uploaded Excel Spreadsheet

I have a friend who takes customer orders, and these customers are required to submit an excel sheet with specific fields such as item, description, brand, quantity, etc. However, the challenge arises when these sheets do not consistently use the same colu ...

What could be causing the need for RxJs TypeScript files to be requested exclusively when my website is hosted on IIS?

When I develop my site using Visual Studio / IIS Express, everything runs smoothly without any unusual requests or 404 errors. However, once I publish the site to IIS and try to run it, I start receiving multiple requests for typescript files (.ts), prima ...

React Material-UI is notorious for its sluggish performance

I recently started using React Material-ui for the first time. Whenever I run yarn start in my react app, it takes quite a while (approximately 25 seconds) on my setup with an i5 8400 + 16 GB RAM. Initially, I suspected that the delay might be caused by e ...

Is there a way to ensure that the observer.next(something) received the value before executing observer.complete()?

I have been working on an Angular app where I am using a resolver to preload data in the component. Below is the code for the resolver: resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): void { return Observable.create(observer => { ...

Utilizing TypeScript to Populate an observableArray in KnockoutJS

Is there a way to populate an observableArray in KnockoutJS using TypeScript? My ViewModel is defined as a class. In the absence of TypeScript, I would typically load the data using $.getJSON(); and then map it accordingly. function ViewModel() { var ...

Unable to activate the AWS IoT security audit using CDK

I'm trying to activate the AWS IoT security audit using a CDK stack, but I'm encountering some issues. Initially, I referred to this documentation for the interfaceAuditCheckConfigurationProperty and implemented the following CDK code to enable ...

Utilize the term "export const" twice when declaring variables to assign value

const foobar = { foo: 'hello', bar: this.foo }; The code isn't working as expected, returning "undefined". Any suggestions on how to properly access it? ...

Controlling Ionic 3 slides on a separate page

I have a collection of slides on one page, each slide representing a different page. I am looking to create a functionality where clicking a button on one of the pages will advance the slide to the next one: slides-page.ts @ViewChild(Slides) slides: Slid ...

What could be causing the availability of a response in a service, but showing as undefined in the component?

Currently, I am facing a problem with my service and component setup. While the service can successfully read the response as a JSON object, the component is returning res: undefined. service: constructor( private http: Http, private fbuilder: Fo ...

Utilizing the [mat-dialog-close] directive within an Angular dialog component

While attempting to utilize the suggested code in the dialog template for opening a dialog component to either confirm or cancel an action, I encountered an error with the following message. Why did this happen? Property mat-dialog-close is not provided by ...

Facilitating the integration of both Typescript and JavaScript within a Node application

We are currently integrating Typescript into an existing node project written in JS to facilitate ongoing refactoring efforts. To enable Typescript, I have included a tsConfig with the following configuration: { "compilerOptions": { "target": "es6", ...

Tips on creating a Jasmine unit test scenario for a function that triggers onerror of an image tag

I am facing an issue with the code below as the test case is failing //test case it('should display default image if the image link in people finder result does not exist', fakeAsync(() => { debugger component.resultsItem = M ...

Accessing Slider Value in Material-UI

I am currently utilizing the Material-UI Slider and I am looking to retrieve the value using the onChange function. This is what my code looks like: const SliderScale: React.FC = () => { const classes = useStyles(); const [inputValue, setInputValue ...

I'm having trouble with one of my filter pipes not displaying any results. Can anyone help me troub

I have recently included a new filter for DL, but it seems that the results are not showing up as expected. Any ideas on what changes I should implement? <div class="form-group float-left mr-4"> <strong>DL</strong> <br /> ...