What is the process of type checking in Typescript when passing arguments?

I'm curious about TypeScript and why the two function calls below result in different type checking outcomes. Can someone shed some light on this for me?

interface LabelledValue {
    label: string;
}

function printLabel(labelledObj: LabelledValue) {
    console.log(labelledObj.label);
}

var myObj = {size: 10, label: "Size 10 Object"};

//The type checking is successful with this call

**printLabel(myObj);**

//However, an error is flagged with this call stating "size does not exist in LabelledValue"

**printLabel({ size: 10, label: "Size 10 Object" });**

Thank you in advance.

Answer №1

The decision to flag excess properties in object literals as errors in TypeScript is intentional. It is likely that having extra properties is a mistake, so the compiler catches it as an error. In scenarios like the second call of the printLabel function mentioned in your query, if the size property is not being used, there is no need for it to be included in the object literal.

The documentation explains:

In cases like these, TypeScript considers the presence of additional properties in object literals a potential issue. When assigning object literals to other variables or passing them as arguments, they undergo excess property checking. If an object literal contains properties that the "target type" does not define, an error will be triggered.

Answer №2

When it comes to the first scenario, typescript automatically converts an object with properties { size: number, label: string } to type LabelledValue, and this conversion goes smoothly without any issues.

However, in the second case, typescript interprets that you are attempting to construct an object of type LabelledValue. As a result, it throws an error because size is not a recognized property within that type definition.

If you were to declare a specific type for myObj in the first situation, like this:

var myObj: LabelledValue = {size: 10, label: "Size 10 Object"}; // this will trigger a compiler error

I'm not entirely sure about your objective here, but one potential solution could be to include size as an optional property within your interface, such as:

interface LabelledValue {
    label: string;
    size?: number;
}

Answer №3

Within Typescript, there are scenarios where potentially unsound operations that cannot be determined during compile-time are made secure.

displayLabel(myItem);  // operation with potential soundness issues

According to the Typescript handbook:

The guiding principle of TypeScript's structural type system is that x is considered compatible with y if y includes at least the same properties as x.

In this case, item is deemed type-compatible with LabeledValue because item possesses all the necessary attributes that LabeledValue demands (i.e., label: string).

Nevertheless, an error will occur in the following scenario as object literals can solely define recognized properties:

displayLabel({ height: 20, label: "Height 20 Object" });  // ERROR

To rectify this issue, you simply need to cast the object literal explicitly as <LabeledValue>:

displayLabel(<LabeledValue>{ height: 20, label: "Height 20 Object" });  // OK

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

Passing a value from an HTML template to a method within an Angular 4 component

Encountering an issue with Angular 4. HTML template markup includes a button: <td><a class="btn btn-danger" (click)="delete()"><i class="fa fa-trash"></i></a></td> Data is assigned to each td from a *ngFor, like {{ da ...

In the process of using SWRInfinite for React Infinite Scrolling, the initial call may be made

Can someone help me understand why my useGetItems hook, which imports the usePagination hook, keeps repeating the first call history every time I scroll? /items?_page=1&_limit=40 /items?_page=1&_limit=40 /items?_page=2&_limit=40 /items?_page=1 ...

The outcome of array.splice is null

Recently, I've delved into learning angular4 and typescript. If this seems like a simple question, bear with me. Within my angular service, I've defined a method: removePerson(person: Person): Promise<void> { return Promise.resolve( ...

Share images and additional data in Nativescript using TypeScript and Angular without the need for FormData

I gave this a try but unfortunately Send FormData with other field in Angular didn't work for me. I'm looking to retrieve an image from the file system and then send it. let fullPath = path.join(folder.path, "1.png"); const imageFromLocalFile: ...

What is the best way to integrate the Telegram login widget into an Angular application?

Does anyone know how I can integrate the Telegram login widget into my Angular application without resorting to hacks? The required script is as follows: <script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-login="bot_name" ...

Angular 6's observable variable doesn't properly support Ng If functionality

I successfully implemented server-side pagination in the Angular6 material data grid following the instructions from this link. Now, I am facing an issue where I want to display a "No Data Found" message if the response dataset is empty. I tried using ngI ...

Pass an object and a string variable using Jquery Ajax

As someone new to creating Ajax calls, I am curious about whether it is feasible to include more than one parameter in an Ajax call. Currently, in my $.ajax function, I am attempting to send an object and a string. $.ajax({ type: 'POST& ...

Exploring the concept of inheritance and nested views within AngularJS

I've encountered a challenge while setting up nested views in AngularJS. Utilizing the ui-router library has been beneficial, but I'm facing issues with separate controllers for each view without proper inheritance between them. This results in h ...

The code encountered an error with message TS2345 stating that the argument type '(a: Test, b: Test) => boolean | 1' cannot be assigned to a parameter type of '(a: Test, b: Test) => number'

Apologies for the lengthy subject, but I am having trouble understanding the response. Here is my code snippet: this.rezerwacjeFilteredByseaarchInput.sort(function (a, b) { if (a[5]===null) { // console.log(a[5]); return 1; } ...

Navigating to the main directory in Angular 2

I am currently diving into the world of Angular 2 and attempting to create my very first application. I am following a tutorial from Barbarian Meets Coding to guide me through the process. Following the steps outlined in the tutorial, I have set up my appl ...

What is the purpose of having multicharacter literals in the C and C++ programming languages?

I recently discovered that C and C++ actually support multicharacter literals, such as 'tralivali', which are of type int rather than the expected char in C or C++. This was quite surprising! enum { ActionLeft = 'left', ActionRi ...

JSX tags without any inner content should be self-closed

After successfully running this code, I encountered an issue when committing it to git. The error message 'ERROR: src/layouts/index.tsx:25:9 - JSX elements with no children must be self-closing' appeared. I attempted to resolve the error by addi ...

Simulating MatSnackBar in Angular 8 using Jasmine Testing

My Angular 8 application utilizes the Angular Material MatSnackBar, and I am currently in the process of testing whether the open() method of this class is triggered. The invocation of open() happens within an NgRx store selector as shown below: ngOnInit( ...

Is there a way to verify if an object adheres to a specified interface?

Let's say I have a custom interface called MyInterface Is there a built-in method in TypeScript that allows checking if an object adheres to the MyInterface ? Something similar to using instanceof but for interfaces instead of classes. ...

Transfer your focus to the following control by pressing the Enter key

I came across a project built on Angular 1.x that allows users to move focus to the next control by pressing the Enter key. 'use strict'; app.directive('setTabEnter', function () { var includeTags = ['INPUT', 'SELEC ...

Leveraging bespoke components for data within Ionic 2

I have designed a custom component that functions like this: student.ts import { Component, Input } from '@angular/core'; @Component({ selector: 'student', templateUrl: 'student.html' }) export class StudentComponent { ...

Display responsive input field based on selected option in ionic2 dropdown menu

When the user selects 'Other' from the dropdown menu using Ionic2 and Angular2, I want to provide them with an option to enter their profession. Here is a visual representation of the select box: https://i.sstatic.net/CRjAl.png Below is the co ...

Issue with the Mat paginator items per page functionality not functioning properly in Angular 9

I have encountered an issue where changing the items displayed per page on a table I'm rendering from an observable is not functioning as expected. Despite trying methods such as ngAfterViewInit and calling page events, I did not see any changes. ...

Apologies, but it seems there was an issue with the installation of the "@angular/compiler-cli" package

Despite thoroughly searching through various threads, I am still unable to find a solution to my problem. I have cloned the angular2 quickstart project and ensured that all module versions are up to date. For reference, here is the link to the repository ...

Can TypeScript interfaces be used with various types?

Currently, I am receiving data from an endpoint that is providing a collection of different types all following the same interface. The structure looks something like this: interface CommonInterface { public type: string; public commonProperty1: i ...