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

Distributing JWT to the recipient using Express

Allow me to provide you with an overview of my application, which is quite straightforward. The main concept revolves around a user inputting their accountname and password into an html form on the /Login page like so: <form action="/Login" m ...

Different approaches for expanding object.prototype while utilizing jQuery

Once upon a time, I made the mistake of trying to extend Object.prototype and ended up encountering errors in my jQuery file. After doing some research, I found out that extending Object.prototype is frowned upon in the JavaScript community due to potentia ...

Utilizing Vuex to manage the state of modal components within a list of child components

I am attempting to utilize vuex to maintain a value that controls the visibility of a modal in a child component. The parent component renders the child component multiple times in a list, but the modal consistently displays only the last item in the list. ...

I am struggling to display the data fetched by Next.js on the page

I am struggling to display the data from the first file in my tanstack table or as a string within the HTML, even though I can see it in a console.log when grabbed by axios. The tanstack table worked fine with hardcoded data. In the console image provided, ...

Only if there is an update in the SQL database, I wish to refresh the div

I have created a voting system and I am facing an issue with the data updating. I have implemented a setInterval function in javascript to load the data every 2 seconds, but it's not working as expected. There are no errors shown, but the data is not ...

What could be causing the RTCPeerConnection icegatheringstatechange to not function properly?

I have been trying to utilize the icegatheringstatechange event handler, but it doesn't seem to be functioning properly. Is there a different method I can use to monitor changes in icegatheringstate? How can I determine when all ice candidates have be ...

Typescript having issues compiling to commonjs/es2015 accurately

I currently have Node v14.5.0 installed and I'm using ts-node-dev in my development environment However, I am encountering an error every time I try to compile to JS. Initially, I attempted with the following tsconfig: "target": "es5& ...

Is it possible to import multiple versions of a JavaScript file using HTML and JavaScript?

After extensive research, I am starting to think that using multiple versions of the same JavaScript library on a single page is not possible (without utilizing jquery Can I use multiple versions of jQuery on the same page?, which I am not). However, I wan ...

Submit data via POST method on the modified URL

I need assistance with modifying the data of a URL and making a POST request to it. The URL in question is as follows: http://domanin.com/search-result/?start=06%2F08%2F2017&end=06%2F09%2F2017&room_num_search=1&adult_number=1&children_num= ...

Utilizing Typeahead for Autocomplete in Durandal: A Step-by-Step Guide

I am attempting to implement an autocomplete input field with typeahead (Twitter Bootstrap) in a modal, but I am encountering difficulties making it function properly. Additionally, this autocomplete field needs to be observable with Knockout so that selec ...

A handy tip for sending a response once a for each loop has finished executing

It is important that Response.json executes only after the foreach loop has completed its execution. var todoarr = (req.body.data) ? req.body.data : undefined todoarr.forEach(function(element) { if(element.done == true) { TodoS ...

What distinguishes between the methods of detecting falsy and truthy values?

While working with JavaScript / Typescript, I often find myself needing to verify if a length exists or if a value is true or false. So, the main query arises: are there any differences in performance or behavior when checking like this... const data = [ ...

Node.js data transmission: Sending information from server to client

In my node project, PUG/Jade files are used to render webpages. Every minute, a JS file updates a redis database and I want the GUI to reflect these changes without requiring a page refresh. Here is an overview of how the data is currently passed: User ...

The breakpoint was overlooked due to the absence of generated code for TypeScript on a Windows operating system

Currently, I am in the process of debugging a TypeScript project. The structure of the project folder and tsconfig.json file is illustrated below: Furthermore, my launch.json file is displayed below: While attempting to debug, I have noticed that .map fi ...

Why does everything seem to move in sync with the table's scrolling?

I recently had an issue resolved that fixed most of my concerns: I needed to make three separate edits, and now when I reintroduce the other two edits, they are included within the table section and scroll along with the table instead of being stuck beneat ...

Using Angular.JS to iterate over a nested JSON array using ng-repeat

I am currently working on a People service that utilizes $resource. I make a call to this service from a PeopleCtrl using People.query() in order to retrieve a list of users from a json api. The returned data looks like this: [ { "usr_id" : "1" ...

Having trouble with selecting JS dropdown options in Python Selenium

My HTML view- Check out the website design HTML code- View the HTML code here When I click on the dropdown arrow, a new code appears - view the code snippet Although my code successfully displays the dropdown options, it does not allow for selecting an ...

What is the best way to increase a count in MongoDB?

I need to update the quantity count in my database every time I click a specific button. Here is the Angular directive I am using: var count = 0 $scope.postNote = function () { var deferred = $q.defer() var token = $scope.userInfo.$$state.valu ...

What are the steps for transforming my 2D array to fit a specific schema using RxJS?

UPDATE I stumbled upon a potential solution that I have appended to my question and am now seeking a more refined approach. In the context of an Angular 9 application, I am working with a two-dimensional array that I need to restructure. Through my use of ...

Preventing Express.JS HTTP requests from being blocked by npm cron

I'm experimenting with the cron module from npm within my Express.js application. The structure of my app is quite straightforward. I have a function to establish a connection to the database, where I then register all the different modules that hand ...