In TypeScript, if all the keys in an interface are optional, then not reporting an error when an unexpected field is provided

Why doesn't TypeScript report an error when an unexpected field is provided in an interface where all keys are optional? Here is the code snippet:

// This is an interface which all the key is optional
interface AxiosRequestConfig {
  url?: string;
  method?: string;
  baseURL?: string;
  headers?: any;
  params?: any;
  paramsSerializer?: (params: any) => string;
  data?: any;
  timeout?: number;
  timeoutErrorMessage?: string;
  withCredentials?: boolean;
  responseType?: ResponseType;
  xsrfCookieName?: string;
  xsrfHeaderName?: string;
  onUploadProgress?: (progressEvent: any) => void;
  onDownloadProgress?: (progressEvent: any) => void;
  maxContentLength?: number;
  validateStatus?: ((status: number) => boolean) | null;
  maxBodyLength?: number;
  maxRedirects?: number;
  socketPath?: string | null;
  httpAgent?: any;
  httpsAgent?: any;
}

"a" field is unexpected, why TypeScript does not report an error ?

type test= {
  [key:string]: (...args:any[])=> AxiosRequestConfig
}

const serviceMap: test = { 
  getOperationLogListByConditions(conditions: any) {
    const { 
      currentPageIndex,
      createTimeStart,
      createTimeEnd,
      ...rest
    } = conditions

    return {
      url: '/operateLog/page',
      method: 'GET',
      params: {
        ...rest,
        pageNo: currentPageIndex,
        createTimeStart: encodeURIComponent(createTimeStart),
        createTimeEnd: encodeURIComponent(createTimeEnd)
      },
      a:"" // "a" field is unexpected, why TypeScript does not report an error ?
    }
  }

I am unsure why this is happening, please provide some insight! The TypeScript version being used is 4.1.2.

Answer №1

The validation process for excess properties is not activated when dealing with return types, which explains why no error message is displayed for the extra field a. The optional nature of all properties in AxiosRequestConfig is irrelevant. explore playground

In contrast, the excess property check is enforced for expressions and variables in assignment statements, as well as for argument and parameter types in function calls.

interface Props1 {
  age: number;
}

// Excess property check triggered due to expression assignment
let x: Props1 = {age: 1, test: "tutu"}; 

function returnProps1(): Props1 {
  let props = {age: 1, test: "tutu"};
  // Return type does not trigger excess property check
  return props
}

The excess property check also applies to "fresh" object literal assignments. However, freshness can be lost through type assertion and widening. In your scenario, the freshness is compromised by type assertion since the returned type is not specified in your function definition.

const serviceMap: test = { 
  getOperationLogListByConditions(conditions: any) {
    const { 
      currentPageIndex,
      createTimeStart,
      createTimeEnd,
      ...rest
    } = conditions
    
    // Freshness of object literal lost due to type assertion
    // No excess property check triggered
    return {
      url: '/operateLog/page',
      method: 'GET',
      params: {
        ...rest,
        pageNo: currentPageIndex,
        createTimeStart: encodeURIComponent(createTimeStart),
        createTimeEnd: encodeURIComponent(createTimeEnd)
      },
      a:"" // Unexpected "a" field without TypeScript error reporting
    }
  }

To maintain object literal freshness, one solution is to specify the return type in the function definition.

const serviceMap: Test = { 
  getOperationLogListByConditions(conditions: any): 
  AxiosRequestConfig {
    const { 
      currentPageIndex,
      createTimeStart,
      createTimeEnd,
      ...rest
    } = conditions

    // No type assertion
    // Object literal remains fresh
    // Excess property check triggered
    return {
      url: '/operateLog/page',
      method: 'GET',
      params: {
        ...rest,
        pageNo: currentPageIndex,
        createTimeStart: encodeURIComponent(createTimeStart),
        createTimeEnd: encodeURIComponent(createTimeEnd)
      },
      a:"" // Error message should be displayed
    }
  }
}

check out playground

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

Encountering compilation issues when transitioning from Angular 7 to Angular 8

Upon upgrading my project to Angular 8, an unexpected error occurs during the build process: ERROR in HostResourceLoader: loader(C:/myapp/cli/src/app/pages/user-home/user-home.component.html) returned a Promise i 「wdm」: Failed to compile. Ho ...

A guide to using Angular to emphasize text based on specific conditions met

Currently, I am developing a testing application that requires users to choose radio type values for each question. The goal is to compare the selected answers with the correct answers stored in a JSON file. To achieve this, I have implemented an if-else ...

Utilize the index of a for loop to manipulate an Angular string

When working with different objects and creating forms simultaneously, I've come across a challenge. My initial idea for handling the submission was to use the following code: <form (ngSubmit)="submitForm{{u}}()"> However, incorporating the in ...

When using create-react-app with JEST to run tests, TypeScript errors are not displayed

When I write incorrect TypeScript code in my project set up with create-react-app, running tests using npm test does not show any errors in the terminal. Is this normal behavior? It would be helpful to see these errors to avoid writing incorrect TypeScript ...

Managing a MySQL database in NodeJS using Typescript through a DatabaseController

I'm currently working on a restAPI using nodejs, express, and mysql. My starting point is the app.js file. Within the app.js, I set up the UserController: const router: express.Router = express.Router(); new UserController(router); The UserControll ...

What steps should I take to troubleshoot this Angular issue within a Visual Studio 2022 project that utilizes the Standalone Angular template?

After going through this tutorial and meticulously following each step, I encountered an error when trying to run the application: https://i.sstatic.net/EvYgg.jpg Can anyone advise on how to resolve this issue? I'm facing a similar error while attem ...

TypeScript does not properly validate the types of defaultProps

When working with TypeScript 3.0, I consulted the documentation at https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html The recommendation is to use static defaultProps: Pick<Props, "name"> as an explicit type annotation ...

The Typescript compiler is throwing an error in a JavaScript file, stating that "type aliases can only be used in a .ts file."

After transitioning a react js project to react js with typescript, I made sure to move all the code to the typescript react app and added types for every necessary library. In this process, I encountered an issue with a file called HeatLayer.js, which is ...

Tips for maintaining the active state of an item within a component that loops through a dataset

I am working with an array of objects (specifically, posts represented as strings) and I am looking to be able to edit each one individually. However, I am encountering an issue where clicking on the edit button triggers editing for all posts at once: co ...

Having trouble accessing a custom factory within a directive in Angular using TypeScript

Having some trouble with my injected storageService. When trying to access it in the link function using this.storageService, I'm getting an undefined error. Any assistance on this issue would be greatly appreciated. module App.Directive { import ...

Using React with Typescript to display components generated from the `map` function

In my scenario, I have retrieved data from a JSON file and am also utilizing a utility function that selects 5 random entities from an object Array. This particular array contains 30 entities. Struggling with displaying the 5 random jockeys stored in the ...

Avoid invoking a TypeScript class like a regular function - _classCallCheck prevention

I am currently developing a TypeScript library that needs to be compatible with all versions of JavaScript. I have noticed that when calling a class in TS without using new, it does not compile properly, which is expected. In ES6/Babel, a class automatica ...

Prevent click events on disabled tabs in PrimeNG tabMenu

I am encountering an issue with PrimeNG's p-tabMenu when it comes to disabled menu items. For example, suppose I have a tabMenu with 4 sub tabs labeled AAA, BBB, CCC, and DDD. This is how the menuItems are set up in the TypeScript component: //.... ...

Problems arising from the layout of the PrimeNG DataView component when used alongside Prime

I've been working with a PrimeNG DataView component that requires the use of PrimeFlex's flex grid CSS classes to set up the grid structure. One of their examples includes the following instructions: When in grid mode, the ng-template element ...

Get detailed coverage reports using Istanbul JS, Vue JS, Vue CLI, Cypress end-to-end tests, and Typescript, focusing on specific files for analysis

I have a VueJS app written in Typescript that I am testing with Cypress e2e tests. I wanted to set up coverage reports using Istanbul JS to track how much of my code is covered by the tests. The integration process seemed straightforward based on the docum ...

Broadcasting TypeScript Data Structures via Socket.IO

In my Typescript code, I have created a basic User class as shown below: export class User { constructor(public id: string); } When I emit a message from my socket.io server, I include an instance of the User class like this: var user = new User(&ap ...

What is the process of converting an Array that is nested within an Object?

I am facing compile errors while attempting to convert an Object containing an Array of Objects. Here is the initial structure: export interface CourseRaw { metaInfo: MetaInfoRaw; gameCode: number; gameText: string; images?: ImageRaw[]; // Having ...

Prevent users from clicking buttons until all mandatory fields are filled out using react-hook-form

I am seeking guidance on how to dynamically disable a button based on the input values of both Name and State in the given code snippet. Specifically, I want to restrict button functionality until both name and state fields are filled out, regardless of ...

TS2322 error: Attempting to assign type 'any' to type 'never' is invalid

Currently, I am utilizing "typescript"- "3.8.3", and "mongoose": "5.9.11". Previously, my code was functional with version "typescript": "3.4.x", and "mongoose": "4.x". Here is a snippet of my code: https://i.stack.imgur.com/j3Ko2.png The definition for ...

Issue with the drag functionality of Framer Motion carousel causing malfunction

Attempting to create a basic Image Carousel using framer-motion for added functionality. The goal is to incorporate both buttons and drag control for sliding through the images. Currently, it functions properly, but if the slider overshoots on the last im ...