In Typescript, it is possible to assign properties to an object that are not explicitly defined in the object's type definition

I'm confused as to why Typescript isn't flagging this as an error...

When I conditionally add a new property to an object that doesn't exist in the type definition, Typescript still allows it

  type Filters = {
      keywords: Array<string>
    }
    
    const condition = 1;
    
    let filters: Filters = {keywords: ['keyword']}
    
    filters = {
      ...filters,
        ...(condition && {...{ tags: ['tag']}}),
      }

Results:

filters: {
  keywords:["keyword"]
  tags:["tag"]
}

However, I was expecting the following error:

Object literal may only specify known properties, and 'tags' does not exist in type 'Filters'.

Note: I do get the expected error when trying to add the same property like this:

filters = {...filters, tags: ['tag']}

Answer №1

Currently, TypeScript is missing a key feature; excess property checks are only performed in specific contexts and there is no implementation for checking the content of inline objects that are spread into outer objects.

An open feature request regarding this issue can be found at microsoft/TypeScript#39998. It is currently awaiting more feedback, so it might be helpful to go to the issue, give it a thumbs up, and explain your use case and why it is important. While it may not have a significant impact, it's worth a try.


As of now, there isn't a perfect workaround to achieve this behavior. One approach could be using a helper function like:

const noExcess = <T extends object>() =>
  <U extends { [K in keyof U]: K extends keyof T ? T[K] : never }>(u: U) => u;

Specializing it for Filters:

const noExcessFilters = noExcess<Filters>();

And then utilizing it:

const z = noExcessFilters({
  ...filters,
  ...(condition && { tags: ['tag'] }),
}); // error!   Types of property 'tags' are incompatible.

This method will flag problematic situations, but the effectiveness may vary for you.

Link to Playground with code snippet

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

The email provided is invalid according to the response received from the Campaign Monitor API within a Meteor JS

I'm currently facing an issue with a project using Meteor. I'm attempting to add an email address to a subscriber list through the Campaign Monitor API. To do this, I'm utilizing a npm package called createsend-node, which acts as a wrapper ...

Having received a status code of 200 in Flask WebApp, I am still unable to access the page

Currently in the process of developing a webapp using Flask, I have created the homepage where users are required to input their phone number and password. Once entered, the system will send an OTP to the provided phone number. When clicking the signup bu ...

How to send a Javascript variable to Django views.py using getJSON

With a javascript variable named myVariableToSend containing a single string, I am seeking to pass it to my views for executing raw SQL queries in the database. Afterward, I aim to retrieve the corresponding data and send it back to my Javascript code. Bel ...

What are some alternative ways to utilize jQuery siblings() without restricting it to the same parent element?

In the code provided below as Non-functional code [1], it will function correctly with siblings() to disable other input fields if their sum or amount exceeds a specified maximum value. This works effectively when all input fields are within the same paren ...

Tips for updating data within an array using a copied object

Just starting out with JavaScript Could you assist me with a basic inquiry, please? For instance, I have an array like this: const array = [{ id: 1, name: 'Ferrari', type: 'F40', price: '350 000$', countr ...

Utilize dynamic Google Maps markers in Angular by incorporating HTTP requests

Struggling to find a solution for this issue, but it seems like it should be simple enough. Initially, I fetch my JSON data using the code snippet below: testApp.controller("cat0Controller", function($scope, $http){ var url = "../../../Data/JSONs/randomd ...

Typescript indicates that an object may be potentially null

I've hit a roadblock where I keep getting warnings that the objects might be null. After searching online and on StackOverflow, I've tried numerous solutions with no luck. My goal is to insert the text "test" into the HTML elements using their ID ...

Directives may not function as expected in the invoked view, however, they work properly on the index.html page

Hello there, I've recently started using AngularJS for building applications and encountered a strange issue. I tried looking for similar problems but couldn't find a solution, which is why I'm reaching out to you all! My project specific ...

How to use JavaScript to validate if an input field is empty in IE

I am facing an issue with the required attribute in IE9. While the attribute works fine in IE10 and above, I am struggling to get it to function in IE9. I have attempted the following: $('#submit-button').click(function(){ if($('#message ...

Implementing Row Highlighting in a Vuetify Simple Table Component

Currently diving into the Vutify documentation to explore v-simple-table and v-data-table, wondering if there's a way to implement row highlighting similar to v-data-table. For reference: Vuetify - How to highlight row on click in v-data-table This ...

What is the best method to make a hyperlink within an IFrame open in a new window?

Let me share the code I've been working on: <!DOCTYPE html> <html> <head> <base target="_blank"> </head> <body> <div style="border: 2px solid #D5CC5A; overflow: hidden; margin: 15px auto; max-width: 800px; ...

clicking on internal links in the bootstrap side menu causes it to jump

Im trying to add a side menu to a help page. The menu and internal links are functioning properly, but when clicked, the side menu partially goes behind the navbar. As a beginner, I'm not sure how to resolve this issue. Can someone offer some guidan ...

What is the method for iterating through rows using csv-parser in a nodejs environment?

I'm working on a script to automate the generation of code for my job. Sometimes I receive a .csv file that contains instructions to create table fields, sometimes even up to 50 at once! (Using AL, a Business Central programming language.) Here is th ...

Using Sequelize and Express API for verification in the controller is an essential component of building

I'm currently working on building the API for my web app, utilizing Sequelize and Express. I have set up models with Sequelize and am in the process of developing controllers and endpoints. My main query is: Should I perform data validation checks be ...

How to extract specific options from a Vue.js multi-select dropdown

I've been struggling to retrieve values from a multi-select box using Vue. My goal is to capture the selected values and submit them to a data source, but I haven't had any success so far. Below is a snippet of my code: <div id="app"> & ...

When merging interfaces and classes, Typescript does not verify property initialization

When creating a class like the following: class Dog { a: string; b: string; c: string; } The TypeScript compiler will throw an error stating that properties a, b, and c are not initialized. However, if we take a different approach like this: i ...

Node Signature Generation for Gigya Comment Notifications

I am currently using the Gigya Comment Notification service within my node application and attempting to generate a valid signature. Despite following the documentation, my code is producing an incorrect hash. Below is the code I am using: var crypto = r ...

Tips on how to lock a dropdown field to prevent editing while retaining the current value

Users on my website can input details about a car into a database and later edit this information on a separate "Edit" page. I want to prevent users from modifying the Make and Model of the car during editing while retaining the original values. I attempte ...

In JavaScript, the code is designed to recognize and return one specific file type for a group of files that have similar formats (such as 'mp4' or 'm4v' being recognized as 'MOV')

I am working on a populateTable function where I want to merge different file types read from a JSON file into one display type. Specifically, I am trying to combine mp4 and m4v files into MOV format. However, despite not encountering any errors in my code ...

Converting Array Class into an Array of Arrays using Typescript

Looking to convert an array class in typescript and pass it to another source. Seeking help on achieving this task in a clean and efficient manner. data : target[] = [{Name : "XXX", Age : "31",DOB : "20-12-1988", Resource: "Java"}, {Name : "YYY", Age : "2 ...