Ensuring that functions retain their original signature when being executed in TypeScript

In my application, I have a method that can accept various types of functions. One specific function called constant exists, and I need to prevent any functions with the same signature from being passed as arguments - all without changing the parameter type of the method.

To achieve this, I made an attempt using instanceof

const constant = (number) => number

class Context {
    execute(fn: (...args?: any) => any) {
        if (fn instanceof constant)
            return false
    }
}

However, it seems that the instanceof operation does not work between functions in this case.

What methods or techniques are there for checking at runtime if a function shares the same signature as another function in TypeScript?

It's worth noting that although I'm asking for a TypeScript solution, vanilla JavaScript approaches would also be suitable if TypeScript cannot provide a more elegant solution.

Answer №1

When discussing runtime, it's important to consider TypeScript. For example, you can analyze the function pattern as a string, although this approach may be considered somewhat unconventional. It begs the question of your ultimate goal, especially when utilizing TypeScript, where running dynamic functions may not be advisable. Nevertheless, below is an illustration of how your resulting JavaScript code might appear.

const constant = (number) => number

class Context {
    execute(fn) {        
         if (typeof fn === 'function' && /\(number\) => /.test(fn.toString())) {
           console.log('Function has same pattern as constant');
         }
    }
}

const inst = new Context();
inst.execute(constant);

Here is the TypeScript version:

const constant = (number: number) => number

class Context {
    execute(fn: (args?: any) => any): void {
        if (typeof fn === 'function' && /\(number\) => /.test(fn.toString())) {
           console.log('Function has same pattern as constant');
         }
    }
}


const inst = new Context();
inst.execute(constant); // true
inst.execute((notNumber: number) => notNumber); // not true

Answer №2

Performing a check at runtime is not possible due to the availability of typings only at compile time. However, you can enforce a constraint using a conditional type to reject any functions with the signature

const constant: (number: number) => number
by setting their type to never.

const constant = (number: number) => number;

type ForbiddenSignature = typeof constant;
//   ^? type ForbiddenSignature = (number: number) => number

class Context {
  execute<T>(fn: T extends ForbiddenSignature ? never : T) {
    // implementation
  }
}

const context = new Context();
context.execute(constant);
//              ~~~~~~~~ Argument of type '(number: number) => number'
//                       is not assignable to parameter of type 'never'.
context.execute((x: string) => {}); // works
context.execute((x: number) => {}); // works
context.execute(() => {}); //works
context.execute((x: number) => 0); // error
//              ~~~~~~~~~~~~~~~~ Argument of type '(x: number) => number'
//                               is not assignable to parameter of type 'never'.

TypeScript 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

Load the page's content gradually, without needing to wait for all the content to be fully loaded

I am facing an issue with a webpage that displays 10 different items, each of which has a slow loading time. Currently, the entire page waits for all 10 items to fully load before displaying anything. I am interested in finding out if it is feasible to sh ...

AngularJS ng-repeat: displaying a list of filtered outcomes exclusively

I currently have a ng repeat that loops through a set of results. <a class="list-group-item" href="#trip/{{trip.id}}/overview" ng-repeat="trip in trips | filter:search | limitTo:-15"> Basically, as I enter more text into my input field, the list sh ...

The CSS ::after selector is experiencing a decrease in animation speed

There is a dropdown menu set to fade in once a link is clicked. Everything works well, the menu fades in properly. However, when clicking off and triggering a function that fades out the dropdown, the triangle on top of the box fades out slightly slower th ...

The Jquery animate function is not compatible with the transform property

I am facing an issue with the Jquery animate function. Despite trying various solutions, I have been unable to get it to work. Below is the HTML code that I have used: <!DOCTYPE html> <html lang="en"> <head> <meta cha ...

Having trouble accessing `event.target.value` when selecting an item from the autocomplete feature in Material-UI with the

*** UPDATED CODE BASED ON RECOMMENDATIONS *** I am currently in the process of familiarizing myself with material-ui. I have been exploring how to incorporate event handling with material-ui components, specifically by combining an autocomplete feature wit ...

"Incorporating text input from a textbox into a <ul> list

Recently I started a new project which involves adding user-entered text from a textbox into a ul list in Bootstrap. The script for this functionality is placed within the head section of my HTML document. <script type="text/javascript"> fun ...

A guide on assigning specific (x, y) coordinates to individual IDs within the tree structure

When attempting to calculate the positions of each ID in order to arrange them hierarchically on the canvas, I encounter some challenges. Whether it's organizing them into a tree structure or multiple trees resembling a forest, one restriction is that ...

Combining Arrays of Javascript Objects with Different Data Types

I have two arrays of objects which I need to combine in a specific way. You can view the arrays here: https://plnkr.co/edit/RQs9WWs1hcxmuKGIgEhM?p=preview My goal is to merge these arrays so that any elements missing from one array are added to create a c ...

Error loading GLTF file

I'm having trouble displaying a GLTF model using three.js. If someone could help me identify the issue in my code, I would greatly appreciate it. import {GLTFLoader} from "./GLTFLoader.js"; var scene = new THREE.Scene(); ...

jQuery's AJAX feature fails to identify the newly modified div classes

For my new website, I am developing a simple checklist feature. To handle the check and uncheck requests from users, I'm using jQuery's $.ajax() function. Whenever a user clicks on the check or uncheck buttons, jQuery retrieves the validation tok ...

Updating JSON when the color changes in Go.js can be achieved by implementing event listeners and

I've been using Go.js for creating Flow charts and saving the json data into a SQL database. However, I'm facing difficulties in updating the json data. Here is the code snippet: myDiagram.addDiagramListener("ChangedSelection", function (e1) { ...

Tips on how to dynamically uncheck and check the Nebular checkbox post-rendering

I incorporated a nebular theme checkbox into my Angular 8 App. <nb-checkbox [checked]="enable_checked" (checkedChange)="enable($event)">Enable</nb-checkbox> I am able to update the checkbox using the Boolean variable "enable_checked". Initia ...

Error encountered while compiling an Asp.Net Core project due to exceeding the maximum allowable path length in the

Encountering a critical error during the build process with Visual Studio 2016 update 3 Asp.Net Core. The build is interrupted with the following message: Severity Code Description Project File Line Suppression State Error MSB4018 The "FindC ...

Tips for updating the color of buttons after they have been selected, along with a question regarding input

I need help with a code that changes the color of selected buttons on each line. Each line should have only one selected button, and I also want to add an input button using AngularJS ng-click. I am using AngularJS for summarizing the buttons at the end ...

Loading animation reminiscent of a whirlpool, similar to the movement

In my quest for the perfect animation, I have scoured far and wide. Unfortunately, the one I found at http://jsfiddle.net/pedox/yed68/embedded/result/ is created using css, which many browsers do not yet support fully. I also explored , but found it to be ...

Ways to determine cleanliness or filthiness in an Angular 5 modal form?

I have a form within a modal and I only want to submit the form if there are any changes made to the form fields. Here is a snippet of my form: HTML <form [formGroup]="productForm" *ngIf="productForm" (ngSubmit)="submitUpdatedRecord(productForm.value) ...

In JavaScript, private variables are not included in the JSON.stringify output

Imagine creating a class called Rectangle with private fields like width and height, initializing them in the constructor. However, when calling JSON.stringify on an instance of this class, it returns an empty object without including the private members. ...

Increasing the height of a jQuery div element and displaying image captions when hovering over them

There is a mysterious 3px gap between the image and the overlay, causing the overlay to extend 3px beyond the height of the image. Switching the CSS to use bottom:3px fixes the issue, but it feels like a hacky solution. The source of this spacing conundrum ...

Encountering obstacles when trying to implement mongoose virtuals in a TypeScript environment

I have been exploring how to utilize virtuals in mongoose with typescript. Let's say I have an interface for defining a user. interface User { id: mongoose.ObjectId; name: string; likes: string; } Next, I define a schema for mongoose. // ...

Customizing vertex sizes in BufferGeometry for diverse shapes

Currently, I am working on creating a 2D scatterplot using three.js and I need to customize the sizes of the points. You can check out my progress here. I'm struggling with adjusting the sizes of the points based on the "radius" property and also addi ...