What is the reason behind the ability to reassign an incompatible function to another in TypeScript?

I discovered this question while using the following guide: https://basarat.gitbooks.io/typescript/content/docs/types/type-compatibility.html#types-of-arguments.

Here is an example snippet of code:

/** Type Heirarchy */
interface Point2D { x: number; y: number; }
interface Point3D { x: number; y: number; z: number; }

/** Two sample functions */
let iTakePoint2D = (point: Point2D) => { /* do something */ }
let iTakePoint3D = (point: Point3D) => { /* do something */ }

iTakePoint3D = iTakePoint2D; // Okay : Reasonable
iTakePoint2D = iTakePoint3D; // Okay : WHAT

It's clear that iTakePoint2D's signature is incompatible with iTakePoint3D. Running iTakePoint2D({ x: 100, y: 200 }) will result in a runtime error, as the program cannot access the value of point.z.

Answer №1

When it comes to TypeScript, function parameters have a special bivariant property, which can either be a blessing or a curse depending on how you look at it. While some may question why this is not flagged as an error by the type system, the reality is that enforcing contravariance (making parameters wider but not narrower than expected) would introduce more errors in common practices. It's a trade-off between correctness and convenience, as explained in the TypeScript Design Non-Goal #3.

The issue of parameter contravariance has been discussed extensively, with considerations for compiler performance being a significant factor in why strict enforcement is avoided. However, there are talks about introducing a compiler flag specifically targeting standalone functions to enforce contravariance, although the timeline for implementation remains uncertain.


Hopefully, this sheds some light on the topic for you. Good luck!

EDIT: Interestingly, the very document you referenced touches upon the implications of bivariance, showcasing both its benefits (seen in event handler code) and drawbacks (illustrated by your example). Perhaps clearer distinctions could have been made in explaining these nuances.

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

There is no index signature that accepts a parameter of type 'string' in the type '{ [key: string]: AbstractControl; }'

I'm currently tackling a challenge in my Angular project where I am creating a custom validator for a reactive form. However, I've encountered an error within the custom validators function that I am constructing. Below you will find the relevan ...

JS- Catching Errors Inside and Outside

Imagine having 2 catch blocks in your code: try { axios.get('https://example.com', {}) .then(function (responseOne: any) { return axios.post('https://example.com', {}, {}) }).then(async function (responseTwo: any) { return a ...

Can the inclusion of a type guard function impact the overall performance of the application?

const typeGuard = (param: any): param is SomeType => { return ( !!param && typeof param === "object" && param.someProperty1 !== null && param.someProperty2 === null ) } If a type guard function similar to the code above is exe ...

The parameter type `SetStateAction<EventDetails[] | undefined>` does not allow for assigning arguments

I am currently facing an issue in a ReactJS project where I am trying to update state that was initially set up like this: const [eventsData, setEventsData] = useState<EventDetails[]>(); Every time I try to update the state using setEventsData(obj), ...

Verify enum values within controller function

I am dealing with a query parameter in my REST API that should be restricted to specific values according to an enum type. I need to find a way to handle a "Bad Request" error if the client provides any value outside of this enum. Here is what my enum loo ...

hide elements only when there is no string to display in Angular2/Typescript

As I experiment with my javascript/typescript code, I've encountered an issue where a string is displayed letter by letter perfectly fine. However, once the entire string is shown, the element containing it disappears and allows the bottom element to ...

Using an array of objects as a data source for the Material Angular table

My user data is causing some issues and looks like this... [{"firstName":"Pinkie","lastName":"Connelly","username":"Darlene.Marvin","email":"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="19506a767b7c75464b7c77777c6b5971766d74 ...

What is the reason that property spreading is effective within Grid components but not in FormControl components?

Explore the sandbox environment here: https://codesandbox.io/s/agitated-ardinghelli-fnoj15?file=/src/temp4.tsx:0-1206. import { FormControl, FormControlProps, Grid, GridProps } from "@mui/material"; interface ICustomControlProps { gridProps?: ...

Secure higher order React component above class components and stateless functional components

I have been working on creating a higher order component to verify the authentication status of a user. Currently, I am using React 15.5.4 and @types/react 15.0.21, and below is a simplified version of my code: import * as React from 'react'; i ...

After deploying to Heroku, cal-heatmap encounters errors despite functioning correctly in a local environment

I successfully implemented a cal-heatmap instance in my Angular 2 (angular-cli) project locally, but when I deployed the project to Heroku, I encountered some errors that prevent the cal-heatmap from displaying. https://i.stack.imgur.com/8gY90.png The er ...

What is the method to ensure that the children of an object strictly adhere to a specific interface or inherit from it?

Is there a way to ensure that an interface extends from another interface in TypeScript? For example: export interface Configuration { pages: { home: IHome; about: IAbout; // How can we make IAbout extend IPage? contact: IPage; }; } inte ...

Error in GoogleMapReact with Next.js: TypeError occurs when trying to read properties of undefined, specifically 'getChildren'

Currently, I am working on a basic nextjs application using the google-map-react component and nextjs. However, I keep encountering an error whenever I try to utilize the component. The error message reads as follows: "TypeError: can't access propert ...

Analyzing the type of object properties from a different perspective

I am new to TypeScript and have encountered many similar questions. I was able to find a solution, but I'm not sure if it's the most efficient one. When constructing the target object as {obj: someObject, prop: "objectPropName"}, I pas ...

How to access elements by their class name in Angular

Recently, I encountered a situation with this specific span element: <span *ngFor="let list of lists[0].question; let i = index" id="word{{ i }}" (click)="changestyle($event)" class="highlight"> {{ list}} < ...

Encountering an issue: JwPagination in angular 9 throws an error of "Cannot read property 'currentValue' of undefined"

Currently using Jw pagination with a page size that changes on 5, 10, or 15 using a dropdown. The Angular version being used is angular 9. The HTML code snippet for this functionality looks like: <div class="col-md-6"> <div ...

Node.js is raising an error because it cannot locate the specified module, even though the path

Currently in the process of developing my own npm package, I decided to create a separate project for testing purposes. This package is being built in typescript and consists of a main file along with several additional module files. In the main file, I ha ...

What are the most optimal configurations for tsconfig.json in conjunction with node.js modules?

Presently, I have 2 files located in "./src": index.ts and setConfig.ts. Both of these files import 'fs' and 'path' as follows: const fs = require('fs'); const path = require('path'); ...and this is causing TypeScr ...

"Angular 4 is requesting a required get parameter that is currently missing

After running my code, I encountered the following console log error: "'Missing required 'page' parameter". I attempted to set this as a parameter in my get request, and it seemed successful because I was able to view the params as an array ...

When invoking a function within another function, it is essential to ensure that both values are returned within the function

When calling a function within another function function1(){ return this.a } function2(){ return this.b } To output in string format, you can call function1 inside function2 function2(){ var resultOfFunction1 = this.function1(); return resultOfFunction1 ...

Customize the position values of the Ngx-bootstrap Tooltip manually

I have incorporated ngx-bootstrap into my Angular 4 application. The component I am using is ngx-bootstrap Tooltip: After importing it, I am implementing it in my component's view like this: <button type="button" class="btn btn-primary" ...