The function does not throw a compiler error when a parameter is missing

Currently utilizing TSC Version 2.4.2

Please take note of the following interface:

interface CallbackWithNameParameter {
  cb: (name: string) => void
}

This code snippet:

const aCallback: CallbackWithNameParameter = {
  cb: () => {}
};

Manages to run without triggering a compile error, despite expectations.

It is worth mentioning that this portion does indeed cause an error:

const aSecondCallback: CallbackWithNameParameter = {
  cb: (num: number) => {}
};

Could this be considered a bug within TSC or is there a misinterpretation on my end? Shouldn't aCallback raise a compile error?

Answer №1

It's important to note that in TypeScript, a function with fewer trailing parameters can be substituted for a function with more trailing parameters as long as the parameter types match. This concept is explicitly addressed in the TypeScript FAQ due to its common occurrence.

The rationale behind this is that any function in JavaScript can be called with any number of parameters, and it is always safe for a caller to send more parameters than expected to a function - the extra parameters are simply ignored. For example:

const aCallback: CallbackWithNameParameter = {
  cb: () => {}
};

This code snippet is valid because the aCallback.cb function ignores the first parameter (which must be a string). However, the following case with aSecondCallback would be invalid as it attempts to interpret the first parameter as a number instead of a string, potentially leading to errors.


That pretty much covers the basics. Good luck!


Update 1

In response to an inquiry by @jbmilgrom, about why aCallback.cb() results in a compile error although its definition seems correct, the explanation lies in the declaration of the type

CallbackWithNameParameter</code for <code>aCallback
. Essentially, TypeScript enforces type constraints based on the declared types, not on actual values, which causes the compile error in this scenario.

A workaround would involve defining a separate interface like so:

interface CallbackWithNoParameter {
  cb: () => void
}

const aCallback: CallbackWithNoParameter = {
  cb: () => {}
};
aCallback.cb(); // this works fine

Regarding substitutability, while you can assign a narrower type to a wider type without issue, attempting the reverse generally results in a compilation error.


Update 2

@jbmilgrom further questioned why TypeScript allows defining something that can never be invoked as defined, pointing out inconsistencies in how substitutable types are handled. The analogy used here likens pouring milk into a container labeled "liquid" (wider type), then expecting it to act like milk when poured into tea, highlighting the confusion caused by type declarations.

To better handle such scenarios, creating explicit type differentiations rather than relying solely on broader types is recommended. Checking if a function accepts zero arguments without causing runtime issues can be challenging, as shown in the provided code snippet.

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

Drizzle-ORM provides the count of items in a findMany query result

Hello there, I'm currently experimenting with the Drizzle ORM and imagine I have this specific query const members = await trx.query.memberTable.findMany({ with: { comments:true } }) I'm wondering how I can retrieve the total count of me ...

Tips for updating the font size of your MUI Accordion title

I was attempting to adjust the font size of the MUI-5 Accordion title. It seems like I need to override it, but I am unsure about how to do so with CSS in MUI-5. Instead of 'SX', it uses 'htmlSx'. When I tried using it, it did not produ ...

How Keyof can render an object undefined and prevent accurate verification

Encountering TS2532 error: Object is possibly 'undefined' while attempting to access an object's value by dynamically selecting the key. TypeScript seems to be restricting me from checking the field values, and I'm unsure of the underly ...

What is the best method for sharing templates and logic in VUE?

Two separate components with shared logic and template, making it appear as though one is extending the other. Think of Drop and Pick components in this manner: // pick.js import Vue from 'vue' import Component from 'vue-class-component& ...

Encountered an error with create-react-app and MaterialUI: Invalid hook call issue

I am encountering an issue while trying to set up Create-react-app with Material UI. The error message I receive pertains to Hooks. Could there be something else that I am missing? This is the specific error message being displayed: Error: Invalid hook ...

Ways to manage drag and drop functionality within Cypress when traditional Cypress techniques are not effective

I need help with the drag and drop function in Cypress. I have tried three different methods but none of them seem to work. I have included my code below, which is not functioning as expected. Does anyone have any suggestions on what might work better in t ...

Exploring the implementation of initiating paypal in NestJs using Jest testing framework

Currently, I am creating a test for a method within NestJs that is responsible for initiating a Paypal Payment intent. When I execute either the yarn test:watch or simply yarn test command, the test described below runs successfully and passes. However, up ...

The implementation of getStaticPaths was done independently of getStaticProps - TypeScript

I am currently in the process of setting up a new blog using a combination of nextJS, TypeScript, and sanity CMS. The homepage is already set up to display posts perfectly. Next on my list is to display the details of each post when it is clicked, based on ...

Is there a way to adjust the width of a table cell in Material UI using React?

I encountered a problem where I am attempting to adjust the width of a table cell, specifically in Typescript. However, I am only able to choose between medium and small sizes for TableCellProps. Is there a workaround for this issue? I am looking to expand ...

Having trouble loading a lazy component in Vue3 with v-if condition?

The code is quite simple. However, I am facing an issue where the about component cannot be rendered. <template> <div id="nav"> <button @click="sh = !sh">{{ sh }}</button> <p v-if="sh">v ...

When viewing an array, the objects' values are displayed clearly; however, when attempting to access a specific value, it

I am attempting to retrieve the board_id of my objects in the columnsServer array... columnsServer: Column[]; this.service.getColumns() .subscribe(data => { this.columnsServer = data; console.log(this.columnsServer); for (this.i = 0; this.i ...

Encountering the error message "This expression cannot be invoked" within a Typescript React Application

I'm working on separating the logic from the layout component in my Typescript React Application, but I suspect there's an issue with the return type of my controller function. I attempted to define a type to specify the return type, but TypeScr ...

Accept an empty string as the defaultValue, but disallow it during validation using Zod, react-hook-form, and Material UI

Currently, I am working with material ui components alongside react-hook-form and zod validation in my project. One of the challenges I encountered is with a select field for a bloodType: const bloodTypes = [ "A+", "A-", "B+", ...

Struggling to transfer array data from service to component

I am currently working on passing an array from service.ts to a component. My goal is to display the array elements in a dialog box. However, I encountered a Typescript error TypeError: Cannot read property 'departmentArr' of undefined. I am str ...

What is the most efficient way to retrieve 10,000 pieces of data in a single client-side request without experiencing any lag

Whenever I retrieve more than 10 thousand rows of raw data from the Database in a single GET request, the response takes a significant amount of time to reach the client side. Is there a method to send this data in smaller chunks to the client side? When ...

AngularJS and TypeScript encountered an error when trying to create a module because of a service issue

I offer a service: module app { export interface IOtherService { doAnotherThing(): string; } export class OtherService implements IOtherService { doAnotherThing() { return "hello."; }; } angular.mo ...

How can TypeScript be used to enable CSV or PDF export in a material-react-table?

Is it possible to incorporate the ability to export data to CSV or PDF in a material-react-table? While I am familiar with how to do this with a Material UI table, I have not been able to find the same functionality for the material-react-table. Thank you ...

Is there an issue with validation when using looped radio buttons with default values in data-driven forms?

Within my reactive form, I am iterating over some data and attempting to pre-set default values for radio buttons. While the default values are being successfully set, the validation is not functioning as expected. <fieldset *ngIf="question.radioB ...

Angular service is able to return an Observable after using the .then method

I am currently facing an issue with retrieving the authentication status in a service method. Everything seems to be working fine except for the return statement. I am struggling with the usage of .then inside .map and I am unable to figure out how to retu ...

Holding an element in TypeScript Angular2 proved to be challenging due to an error encountered during the process

I attempted to access a div element in my HTML using ElementRef, document, and $('#ID') but unfortunately, it did not work. I tried implementing this in ngOnInit, ngAfterViewInit, and even in my constructor. Another method I tried was using @Vie ...