Can an object be required to be spread strictly?

Is there a way to enforce strict spreading of objects in TypeScript?

Consider the example below:

interface Foo {
  a: string;
}

interface Bar {
  a: string;
  b: number;
}

const barObject: Bar = { a: "a string", b: 1 };

// Should generate a warning due to Bar having additional properties (b) compared to Foo
const fooObject: Foo = { ...barObject };

// It currently logs 1
console.log((fooObject as any).b); 

Any suggestions on achieving this level of strictness?

Answer №1

Such an intriguing question! As per this specific issue, the spread operator's purpose is to intentionally avoid triggering excess property checks.


// Despite barObject having more properties than Foo, no excess property checks are triggered by the spread
const fooObject: Foo = { ...barObject };

// 'b' being an explicit property triggers checks in this case
const foo: Foo = { ...bar, b: 2 }

Presently, TypeScript lacks exact types, although implementing a basic type check can help enforce strict object spreading:

// If T and U match, returns T; otherwise, returns never
type ExactType<T, U> = T extends U ? U extends T ? T : never : never

const bar: Bar = { a: "a string", b: 1 };
const foo: Foo = { a: "foofoo" }

const fooMergeError: Foo = { ...bar as ExactType<typeof bar, Foo> }; // error
const fooMergeOK: Foo = { ...foo as ExactType<typeof foo, Foo> }; // OK

To minimize redundancy, we can utilize a helper function:

const enforceExactType = <E>() => <T>(t: ExactType<T, E>) => t

const fooMergeError2: Foo = { ...enforceExactType<Foo>()(bar) }; // error

Explore a sample code snippet here

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

Global error handling in Nest.js: A guide to applying consistent error logic throughout your application

Nest.js I successfully implemented error handling logic as required by the project. Is there a way to reuse this logic for multiple routes in a controller without duplicating the code? @Controller() export class AppController { constructor(private read ...

What steps can I take to restrict a certain character from being inputted into a text field when using Angular's template-driven forms

As I work with angular template-driven forms, a peculiar issue arises when handling the dot character input by users. Rather than allowing it to be added normally to the input field, my goal is to capture the event and switch focus to a different text inpu ...

Implement a class in Typescript that allows for the addition of properties at runtime

I'm currently in the process of incorporating Typescript definitions into an existing codebase that utilizes the Knockout library. Within the code, there is a prevalent pattern that appears as follows: interface SomeProperties { // Assorted prope ...

Angular 6 - a guide to mocking router.events URL responses for unit testing

Looking to simulate router.events in a unit test, as suggested by the title. Within my component, I am using regex to extract the first occurrence of text between slashes in the URL; for example, /pdp/ constructor( private route: ActivatedRoute, ...

flickering effect problem

What could be causing the issue where [@fadeInOut] only works on the initial page load when toggling isExpanded to hide or show content? Due to [@fadeInOut], the content stops showing up. Any thoughts on what might be causing this and any alternative solut ...

Angular error TS2769: None of the available overloads match this call. Overload 1 of 3

I encountered an issue while attempting to retrieve all data from the Firebase real-time database: After removing async from the template, the error disappeared but no data was fetched! I'm confused about what exactly is causing this problem!! This ...

Testing Angular Components - Creating Mocks for AngularFireStore Collection Fetching

Update I made some progress today, but I've encountered a new error in the same process. Updated question below. I'm here with another query regarding how to simulate a complex call from AngularFireStore. I'm facing an issue while running ...

Understanding the return parameter "typeof SomeClass" in TypeScript

typeof in JavaScript returns a string. The TypeScript typings for Sequelize include return types of typeof Model. What does this mean and what is its purpose? I have looked through the documentation but could not find an explanation. Link to Sequelize Typ ...

Attempting to develop a server component that will transmit a JSON result set from a MySQL database located on the local server. What is the best method to send the server object (RowDataPacket) to the

After successfully rendering server-side pages and creating forms with react hooks for database updates, I encountered a challenge in integrating Ag-Grid into my application. Despite being able to retrieve data from the database using the mysql2 module and ...

Connecting peers to servers using WebRTC

While attempting to set up a peer-to-server connection with WebRTC, I struggled due to the lack of TypeScript types in node-webrtc. This made it difficult to add collaborators and disrupted the codebase. Is there an alternative method for establishing a ...

What is the method to update reference models in mongodb by generating documents within a different model?

In my API, I have three models: Patient, Doctor, and Reviews. The Reviews model is referenced in the Doctor model, with the intention that a patient can post a review for a specific doctor using Review.create(). However, even after the review document is c ...

Using Typescript to enclose the object and selectively proxying a subset of its methods

When utilizing the Test class within another class named Wrapper, I aim to be able to delegate the methods to the test instance in a universal manner, like so: this.test[method](). In this scenario, my intention is only to delegate the fly, swim, and driv ...

Converting the Angular 6 HTTP.get response to a string

When I call the GetServiceProviderId() function in my code, I am making a GET request to an API and expecting the result as a string that can be split. GetServiceProviderId() { this.http.get(this.rooturl + 'info', { headers: this.reqHeader ...

Having trouble integrating CKEditor into a React Typescript project

Error: 'CKEditor' is declared but its value is never read.ts(6133) A declaration file for module '@ckeditor/ckeditor5-react' could not be found. The path '/ProjectNameUnknown/node_modules/@ckeditor/ckeditor5-react/dist/ckeditor.js& ...

Is it possible for me to incorporate a new feature into a library that operates using its unique interface?

I'm currently utilizing the angular-gridster2 library and I am looking to add two additional properties in the gridsterItem interface to hold some specific values. How can this be achieved? Despite creating an extended interface of their own, the pack ...

Error in declaring type even after including .d.ts file

I have encountered a situation where the npm package update-immutable does not come with a built-in typescript definition or a definition in @types. To resolve this issue, I created a type definition file within my project. As a result, VS Code is now able ...

Differentiate the array type within an object in TypeScript

I understand how to specify the type for a variable. let members: string[] = [] // this example works flawlessly My goal is to have an array of strings within an object. How can I structure it correctly? const team = { name: String, members<st ...

The consequences of exporting raw .ts files instead of .d.ts files for module type declarations

In a typical TypeScript module, you will find a 'src' directory containing TypeScript source code files. The module compiles these sources using 'tsc -d --outDir dist' to create the 'dist' directory and sets specific package m ...

Errors in Javascript unit testing: despite being stubbed, functions are still being activated

I have encountered issues while writing unit tests, and I am currently facing errors that I am trying to troubleshoot. The specific unit test concerns the index.ts file, which calls the features/index.ts file. To simulate the default export from features/ ...

Step-by-step guide for resolving the issue of "Observable.share is not recognized as a function" in Angular 2

When working with cache structure in Ionic 2, I often encounter an error when defining an observable array to store data retrieved from the server. How can I troubleshoot this issue and resolve it? marketArray : Observable<any>; /* GLOBAL */ th ...