What's the method for validating the spread operator in Typescript?

Is it possible to prevent this code from compiling? (since it currently does...)

const bar: { a: string } = {
    a: '',
    ...{b: ''}
}

Answer №1

It was surprising to discover that this code successfully passed the type checker!

After some investigation, I have a strong suspicion as to why this is happening, though I haven't found any official confirmation yet. Therefore, instead of providing an answer, consider this more of a discussion starter that exceeds the length of a simple comment. In essence, take the following information with a grain of salt.

I believe that TypeScript's "ascription"/"annotation" feature allows for flexibility based on subtypes. Essentially, when we use the syntax:

const foo: Foo = bar;

If the type of bar is a subtype of Foo, it appears to satisfy the type checker without issues. Here's a specific example:

class Foo {
  public a: string;
}

// `Bar` is a subtype of `Foo`
class Bar extends Foo {
  public b: string;
}

const foo: Foo = new Bar();
//         ^^^       ^^^ This works perfectly fine!

Additionally, due to TypeScript's structural subtyping, the following scenario is also valid:

class Foo {
  a: string;
}

// `Quux` is structurally identical to (and therefore a subtype of) `Foo`
class Quux {
  a: string;
}

const foo: Foo = new Quux();

Considering this explanation, your particular example may be accepted because { a: string; b: string } is a subtype of { a: string }.

To sum up, assuming this theory is correct, there may not be a way to compel the type checker to disapprove of your example.

Edit: However, there are some missing pieces to this theory. As noted by @apflieger, this explanation doesn't account for why

const foo: { a: string } = {
  a: 'test',
  b: 'test',
};

gets rejected. It seems like the spreading operation plays a crucial role in this case.

It's possible that the type of

{
  a: 'test',
  ...{ b: 'test' }
}

is inferred as something along the lines of

{ a: string } & { b: string }
, whereas in the previous example it is inferred as { a: string; b: string }.

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

I'm facing an issue with SSRProvider in my NextJs application

My application is developed using NextJs and Typescript, utilizing the react-bootstrap library for creating components. I am facing an issue where I keep receiving an error message stating that When server rendering, you must wrap your application in an &l ...

problem encountered while attempting to drag and drop list elements on a web application utilizing dhtmlx 5.0 and wijmo grid

My web application utilizes Dhtmlx 5.0, Wijmo grid, and Typescript. One feature of the app is a dialog box that displays a list of items which can be rearranged using drag and drop functionality. This feature works without any issues on Windows PCs but enc ...

Maintain the nullability of object fields when casting

I have been working on a type called DateToNumber that converts all the Date properties of an object to number. Here is what I have come up with so far: type LiteralDateToNumber<T> = T extends Date ? number : T extends Date | null ? number | nu ...

In TypeScript, encountering an unanticipated intersection

In my "models" registry, whenever I select a model and invoke a method on it, TypeScript anticipates an intersection of parameters across all registered models. To demonstrate this issue concisely, I've created a dummy method called "getName". expor ...

Perform TypeScript type checks exclusively on a Next.js project

In my current project using Next.js with TypeScript in a mono-repo setup, I have multiple applications under the same repository. When pushing changes to this setup, various hooks are triggered locally to ensure that the modifications meet the required sta ...

Refresh Angular component upon navigation

I have set up routes for my module: const routes: Routes = [ { path: ":level1/:level2/:level3", component: CategoriesComponent }, { path: ":level1/:level2", component: CategoriesComponent}, { path: ":level1", component: ...

Add the specified HTML tag to the existing document. An error has occurred: HierarchyRequestError - The action would result in an invalid node

During my testing of a React/TypeScript project using Jest + Enzyme, I encountered an issue when trying to append an HTML tag. The error occurred with the following unit test code: const htmlTag: HTMLElement = document.createElement('html'); htm ...

Tips on Identifying the Category

I am currently studying TypeScript. Recently, I have been using Axios to fetch API data, and then I stored the returned value in a useEffect hook. However, when trying to display it on the screen, I encountered an error stating that there is no 'name ...

Send a variable from a next.js middleware to an API request

I've been attempting to pass a middleware variable to my API pages via "req" but have encountered some issues Even after trying to send the user token to pages using "req", it consistently returns null The middleware file in question is: pages/api/u ...

The attribute 'disabled' is originally defined as a characteristic within the class 'CanColor & CanDisableRipple & HasTabIndex & MatChipBase'. However, it is replaced in the current context of 'MatChip' as an attribute

After updating my Angular version from 9.1 to 11, I encountered a compilation error. Error: node_modules/@angular/material/chips/chips.d.ts:120:9 - error TS2611:'disabled' is defined as a property in class 'CanColor & CanDisableRipple &a ...

Postgres Array intersection: finding elements common to two arrays

I'm currently developing a search function based on tags, within a table structure like this CREATE TABLE permission ( id serial primary key, tags varchar(255)[], ); After adding a row with the tags "artist" and "default," I aim ...

Preventing the display of the login page for an authenticated user in Angular

My application has different modules for authentication, dashboard, and root routing. The auth module contains routes for sign-in, the dashboard module has routes for home with authentication guard, and the root module redirects to home or a PageNotFound c ...

Enforce boundaries by constraining the marker within a specified polygon on a leaflet map

Currently, I am utilizing a leaflet map to track the user's location. The map includes a marker for the user and a polygon shape. My goal is to ensure that the user marker always stays within the boundaries of the defined polygon. In case the user mov ...

Different methods to prompt TypeScript to deduce the type

Consider the following code snippet: function Foo(num: number) { switch (num) { case 0: return { type: "Quz", str: 'string', } as const; case 1: return { type: "Bar", 1: 'value' } as const; default: thr ...

What is the best way to run tests on this method using Jest?

import { format, getDaysInMonth, getMonth, getYear, isValid, parse } from "date-fns"; export class DateService { public getDaysInMonth(month?: Date) { return getDaysInMonth(month || new Date()); } What is the best way to test this func ...

Concealing a VueJs component on specific pages

How can I hide certain components (AppBar & NavigationDrawer) on specific routes in my App.vue, such as /login? I tried including the following code in my NavigationDrawer.vue file, but it disables the component on all routes: <v-navigation-drawer ...

Executing the Angular 2 foreach loop before the array is modified by another function

Currently, I am facing some difficulties with an array that requires alteration and re-use within a foreach loop. Below is a snippet of the code: this.selectedDepartementen.forEach(element => { this.DepID = element.ID; if (this.USERSDepIDs. ...

Encountering a PropertyTypeError while attempting to process a payment via Stripe in conjunction with use-shopping-cart on Next.js

Upon reaching the checkout page, I encounter the message: Invalid value with type "undefined" was received for stripe. Valid type for stripe is "string". This issue seems to be related to the redirectToCheckout function. Can someone assist me? The cart-s ...

Conflicting TypeScript enum types: numbers and numbers in NestJS/ExpressJS

Incorporating types into my NestJS server has been a priority. After creating a controller (a route for those who prefer Express), I attempted to define the type for params: public async getAllMessages( @Query('startDate', ValidateDate) start ...

TS2322: Subclass missing property, yet it still exists

In my project, I have defined two Angular 4 component classes. The first class, referred to as the superclass: export class SectionComponent implements OnInit { slides: SlideComponent[]; constructor() { } ngOnInit() { } } And then there&apo ...