What is the reason behind TypeScript's decision not to raise an error in case of a mismatched function argument type?

Here's a simple illustration to showcase my point:

type Info = {
    id: number;
}

type ImportantInfo = {
    id: number;
    value: 5;
}

type Task = (data: Info) => void;

const task: Task = data => null;

const data: ImportantInfo = {
    id: 1,
    value: 5,
};

task({ id: 1, value: 5 }); // <== this results in an error because `value` is not part of `Info`

task(data); // <== My question is, why does this not generate an error?

(Also view the TypeScript playground link for an interactive example.)

Why doesn't task(data) trigger an error when the type of data being passed (ImportantInfo) doesn't match the function parameter type Info?

Answer №1

Typescript object types are flexible and extensible, rather than rigid and exact. This means that an object of a certain type can have more properties than what is explicitly defined for that type. Object type definitions only cover the known properties of a type, not all possible unknown properties.

This openness is crucial for interface extension and class inheritance. For example:

interface Payload {
    id: number;
}

interface GreatPayload extends Payload {
    surprise: 4;
}

Here, GreatPayload inherits from Payload with an additional property but is still considered to be a type of Payload. The same concept applies to class inheritance as well.


The only scenario where Typescript treats object types as exact is when creating a new object literal and assigning it to a specific type. This behavior is documented in the "Excess Property Checks" section of the TypeScript Handbook. These checks prevent errors caused by misspelled optional properties or unexpected keys within object literals.


If you wish for exact types to be implemented in Typescript, you can show your support on the related GitHub issue (microsoft/TypeScript#12936). However, since this feature may not be added soon, it's best to work with open types rather than against them. Ensure your code can handle extra properties gracefully by iterating through known keys instead of relying on methods like Object.keys().

Adopting practices that make your code resistant to unknown properties will allow you to safely interact with objects that have more properties than anticipated. Good luck!

Playground link to code

Answer №2

Welcome to Stack Overflow!

Typescript uses type aliases instead of actual "types". According to the documentation, type aliases in some ways resemble interfaces.

In Typescript, objects that implement interfaces can have additional properties without causing errors. That's why the compiler doesn't flag any issues with your action type containing an input instance of GreetPayload.

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

Tips for showing variables in Console directly from the Sources panel?

As I dive into debugging front-end code in Chrome, I am encountering a question that may seem basic to experienced developers. Specifically, while exploring the Sources panel within Chrome's Dev Tools, I find myself hovering over a variable labeled _ ...

Failure to update values in local storage using the React useLocalStorage hook

I've developed two unique custom hooks named useLocalStorage and useAuth. function getDefaultValue<T>(key: string, initialValue: T | null): T | null { const storedValue: string | null = localStorage.getItem(key); if (storedValue) { retur ...

Maintaining the essence of generics while encapsulating functions

I am currently facing a challenge in defining a function that can wrap any other function while maintaining the parameter types and return type. I have managed to achieve this when the function does not use generics, but I am encountering difficulties wi ...

Is it possible to use Vuelidate for password validation in Vue.js?

I found a helpful reference on How to validate password with Vuelidate? validations: { user: { password: { required, containsUppercase: function(value) { return /[A-Z]/.test(value) }, containsLowercase: fu ...

Adding EventListeners for Click Handling: A Step-by-Step Guide

Here is the part of my code in HTML: <!DOCTYPE html> <html> <head> <h> <title> This page</title> </h> </head> <body> <button id = "go-button" >GO ...

Using Material UI with Reactjs for Background Image Mapping

I need some advice from everyone. I have an array of images and I've mapped the content, but for some reason I am unable to set a background image in the styles of a component. The other objects in the array are working as expected. {DlCards.map((mdlc ...

Verifying conditions in an AJAX-based upload system using JavaScript

Recently, I was working on implementing a JavaScript/AJAX upload system with a progress indicator based on a tutorial. The process went smoothly, and I even managed to include a CSS progress bar for visual representation. However, I encountered a hurdle th ...

Optimal method for implementing $scope.$apply(); or $scope in scenarios outside of Angular when working with Angular Components

As outlined in Kendo's best practices, there are instances where Kendo necessitates the use of $scope.$apply(); to update Angular. However, with the emergence of the new AngularJS 1.5 component, it is advised against relying on $scope. The code for t ...

Click and Rotate for More Information

Hello everyone, I have a question regarding creating a unique Tumblr theme. My goal is to make the posts rotate on the y-axis when clicked, revealing like and reblog information. Currently, I've been able to achieve this effect on hover by using code ...

Encountering a problem when launching the "vite-express" template on the Remix app (TSConfckParseError: error resolving "extends")

I recently launched a brand-new [email protected] project using the remix-run/remix/templates/vite-express template after executing this command: npx create-remix@latest --template remix-run/remix/templates/vite-express However, upon trying to run th ...

The challenges of type verification in Redux reducer

I'm currently facing two specific challenges with Typescript and the Redux reducer. Reducer: const defaultState = { selectedLocation: { id: 0, name: 'No Location' }, allLocations: [{ id: 0, name: 'No Location' }], sele ...

Dealing with a large amount of HTML content following an Ajax request: best practices

I'm currently using a method that works fine, but I can't stop thinking about whether there might be a better way to achieve the same result. The task at hand is to display a user profile in a modal box. When a user clicks on a button or link, a ...

Instantiating objects directly from factories in AngularJS

How can I make a direct call to RESTService.get without using AngularJS’ dependency injection in the code snippet below? angular.module('RESTModule', ['ngResource']). factory('RESTService', ['$resource', functio ...

"Optimizing Image Display in Web Browsers

Currently, I am using JavaScript to dynamically size a transparent .gif on my website. The original image size is approximately 200x200 pixels, but it's usually resized to be between 600x600 and 800x800. When viewing the resized image in IE8 and FF3, ...

Jasmine test failing due to uninitialized angular controller

I encountered some difficulties while writing jasmine tests for an AngularJS application that utilizes angular ui-router. Despite proper initialization of my services and app in the test, I found that the controllers were not starting up correctly. In an e ...

Guide for overlaying text on an image in react native

Is there a way to vertically align text over an image in react native? I came across this helpful guide, but I encountered difficulties trying to implement it. Specifically, I couldn't figure out how to nest the text tag within the Image tag. Below is ...

Modifying an array without altering the reference

Perhaps my approach is not quite right, so please provide feedback if necessary! Imagine having an Array that represents some valuable data. var initial = ['x', 'y']; var duplicate = initial; initial.push('z'); console.log(i ...

TinyMCE is substituting the characters "<" with "&lt;" in the text

I am currently using Django with placeholder tags: I am attempting to insert a flash video into my TinyMCE editor, but it is replacing the '<' symbol with < in the code, preventing it from loading properly and only displaying the code. I ...

What might be causing the in-viewport javascript to not work in my code?

Why is my in-viewport JavaScript code not functioning properly? Link to JSFiddle code When the Click to move button is clicked, the cat image will slide correctly. However, when implementing the following code: if($("#testtest").is(":in-viewport")) ...

This error message 'React Native _this2.refs.myinput.focus is not a function' indicates that

When working with React-Native, I encountered a specific issue involving a custom component that extends from TextInput. The code snippet below demonstrates the relevant components: TextBox.js ... render() { return ( <TextInput {...this.props} ...