The Child/Parent arguments in Typescript methods cannot be assigned

Why is this not working in TypeScript?

class Parent {
    id: string = ''
}

class Child extends Parent{
    name: string = ''
}



const fails: (created: Parent) => void = (created: Child) => { return };
const failsToo: ({ created }: { created: Parent }) => void = ({ created }: { created: Child }) => { return };

The error I'm encountering seems quite strange:

Type '(created: Child) => void' is not assignable to type '(created: Parent) => void'.
  Types of parameters 'created' and 'created' are incompatible.
    Property 'name' is missing in type 'Parent' but required in type 'Child'

It appears that it's trying to assign a Parent to a Child, however, in the actual code it's the opposite (attempting to assign a method parameter that is a Child to a Parent. This makes sense because Child is a superset of Parent)

Am I overlooking something?

You can test this out here: https://www.typescriptlang.org/play?#code/MYGwhgzhAEAKYCcCmA7ALtA3gKGn6AlgCYBc0EaCBKA5tALzQDkT2AvttqJDAMIAWBEEWhIAHmlREY8ZOhz5oKMAFskZClVoNmrDpy4B7FBWgAzMEIhkAFMGRhJpOIlRoAlAwB80AG6HiHTsHJzIBISJPeh9MaGQ0AFcEFGg2AG4jEwwLKwAVQ0NbWPskRyQRNjJikPKyWTdUqJ9-QMYbatKnVKroErLncOFG7yw4pETk1LSgA

Answer №1

Contravariant function types involve parameter types that vary in the opposite direction from each other. This concept is a natural consequence of type theory and can be understood by considering passing narrower or wider types to functions than they expect.

const fails: (created: Parent) => void =
    (created: Child) => { created.name.toUpperCase() };

In the above example, assigning a function expecting a Parent to a variable of type

(created: Child) => { created.name.toUpperCase() }
results in a runtime error when trying to access properties of incompatible objects.

TypeScript helps prevent such errors through strict control over parameter widening with the --strictFunctionTypes compiler option enabled.


While widening parameters is not allowed, narrowing them is permissible within contravariant function types. For instance:

class GrandChild extends Child {
    age: number = 1;
}
const okay: (created: GrandChild) => void =
    (created: Child) => { created.name.toUpperCase() };

okay(new GrandChild()); // no issues

The key principle is that input positions like function parameters exhibit a different type variance direction compared to output positions.

Playground link to code

Answer №2

When examining the type definition of fails, it is essential to provide a parent input parameter. This requirement implies that the function's implementation may lead to a runtime error, as shown below:

const fails: (created: Parent) => void = (created: Child) => {
   console.log(created.name)
   return
}

fails({ id: 'foo' })

The code snippet above would result in a runtime failure due to the absence of the "name" field on the passed argument.

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

Bringing PNGs and SVGs into React - Error TS2307: Module not found

While attempting to import PNGs/SVGs (or any other image format) into my React project, TypeScript presents the following error: TS2307: Cannot find module '../assets/images/homeHeroImage.svg' or its corresponding type declarations. The frontend ...

Instructions for utilizing ObjectId with a string _id on the client side

Is there a way to retrieve a document using the _id in string format? Here is an example of the code on the client side: 'use client' ... const Page(){ ... fetch("api/get_data", { method: 'POST', ...

Alternative way to search for child elements within an element without the use of jQuery

I am in the process of creating a universal set of functions to verify the existence of children with specific attributes within a particular element. Unfortunately, I do not have access to jQuery for this task. Here is an example function call: has_chil ...

Node.js exec command encountering an uninformative error message and not executing properly

Here is the snippet of code that needs to be executed cp.exec("cc -Wall /tmp/test.c -o /tmp/test", function(e, stdout, stderr) { if (e) { var errorstr = "There was an error during compilation: "+ e.message.toString() ...

Mapping the preselected values of multiple input fields into an array in Angular 6: A step-by-step guide

When submitting a form with input fields, I need to capture the selected values into an array format like {"userid":1,"newstatus":[1],"mygroup":[1,2,3]}. I attempted using ngmodel but encountered issues. Below is the code snippet: home.component.html & ...

Complete and automatically submit a form in a view using AngularJS

I have developed a basic AngularJS application that is functioning smoothly. Currently, I am looking to populate certain fields and submit the form directly from the view without requiring any user input. Below, you'll find some simplified JavaScrip ...

Observing changes to attributes in AngularJS is a useful feature that allows for

I am looking to update the attribute of an element by using its id and have the element respond to this change. After trying to showcase my situation in a plunkr, I encountered issues with even getting ng-click to function properly. My goal is to invoke ...

Is there a radio button that can dynamically update and modify the current view?

Although I don't consider my issue to be overly complex, as a newcomer I am struggling to find a straightforward solution. The form I have collects various items and on the output page generates a table based on this data. For instance, one question ...

Is it possible to achieve seamless image transitions in Firefox like it does in Chrome?

To achieve the desired effect, you may need to use some javascript. Visit aditagarwal.com for more information. Styling with CSS: .images-wrapper{ position: fixed; left: 0; top: 80px; bottom: 0; width: 100%; height: 100vh; an ...

Type arguments cannot be accepted in untyped function calls.ts(2347)

My user schema in typescript includes the following interface: interface IUser{ name: string; email: string; password: string; isAdmin: boolean; } Check out the user schema below: const UserSchema = new Schema<IUser>( { name: { type ...

Arrange the JSON object according to the date value

I am working on a JavaScript project that involves objects. Object {HIDDEN ID: "06/03/2014", HIDDEN ID: "21/01/2014"} My goal is to create a new object where the dates are sorted in descending order. Here's an example of what I want: SortedObject ...

How to access vue.js 3 single file component functions from within a script tag

Imagine having a single file component structured like this: <template> // content irrelevant </template> <script> export default { data() { return { redLocations: [ "Isfahaan", "Qom", ...

Error loading Azure Active Directory web form: Server returned a 401 status code for the requested resource

I recently made changes to my web site (incorporating a web form and entity framework) to use AAD connection, following the guidance in this insightful blog post. However, I am encountering an issue where scripts and css files are not loading properly. Th ...

Sometimes jQuery may require multiple executions with just one click

Content of index.php <script type="text/javascript" src="//<?php echo $_SERVER["SERVER_NAME"];?>/javascript/jquery-1.10.2.min.js" ></script> <script type="text/javascript"> $(document).ready(function() { $( document ).on( 'c ...

Initiate an Ajax request solely for the elements currently visible on the screen

I am currently facing an issue that requires a solution. Within our template, there are multiple divs generated with the same classes. Each div contains a hidden input field with the ID of the linked target site. My task is to utilize this ID to make aja ...

`Automatic toggling between two inputs with adjustable settings`

There are 2 input fields in my code that only accept positive floats with 2 decimals. Any other characters entered should be automatically removed using the change() function. Whenever the value of one input is changed, the value of the other input should ...

Error message when using Vue Global Filter: Value undefined is not defined

Trying to format currency, I initially attempted to use a global filter in Vue: Vue.filter('formatMoney', (val) => { if (!value) return '' val = val.toString() return val.replace(/\B(?=(\d{3})+(?!\d))/g, ",") ...

The content security policy is preventing a connection to the signalr hub

Currently, I am developing an application using electron that incorporates React and Typescript. One of the features I am integrating is a SignalR hub for chat functionality. However, when attempting to connect to my SignalR server, I encounter the followi ...

Is it feasible to obtain the userId or userInfo from the Firebase authentication API without requiring a login?

Is it feasible to retrieve the user id from Firebase authentication API "email/password method" without logging in? Imagine a function that takes an email as a parameter and returns the firebase userId. getId(email){ //this is just an example return t ...

Tips for emphasizing a searched item in V-data-table using VueJS

Is it possible to highlight a specific value in a v-data-table by searching for a particular word? Below is a snippet of my current code: EDIT: I am using the CRUD-Actions Example from the official Vuetify documentation. https://vuetifyjs.com/en/componen ...