Disallow the use of properties in a nested interface

Is there a way to define an interface or type that restricts a specific key in a child of the interface when used in union types? I am looking for the correct definition for Abc:

type Abc = {
    someField: {
        prohibited?: never,
    },
};
type UsedHere = {someField: {anotherField: string}} & Abc;

I have attempted using the types never, undefined, and void for prohibited, with and without the ?, but Typescript always prompts me to provide a value for prohibited when creating a variable of type UsedHere. How can I make it clear to Typescript that this value should not exist? An example of a valid object would be:

let x: UsedHere = {
    someField: {
        anotherField: ""
    }
}

UPDATE: This issue seems to only persist in pre-3.6 versions of Typescript.

Answer №1

Upon observation, it is evident that the code provided in your example no longer generates an error after TypeScript 3.6. There was a bug reported regarding the improper behavior of excess property checking on deeply nested intersections, which has been resolved. You can find more details about this issue and its fix in microsoft/TypeScript#30715 and microsoft/TypeScript#32582.

If you are using versions of TypeScript prior to 3.6, a workaround will be necessary. One potential solution involves utilizing conditional and mapped types to traverse through object properties within nested intersection types and combine them into single objects. Essentially, transforming something like {a: string} & {b: number} to {a: string; b: number}.

One method to achieve this is by defining:

type MergeIntersections<T> =
    T extends object ? { [K in keyof T]: MergeIntersections<T[K]> } : T;

This approach can then be applied to define UsedHere:

type UsedHere =
    MergeIntersections<{ someField: { anotherField: string } } & Abc>;
/* type UsedHere = {
    someField: {
        anotherField: string;
        prohibited?: undefined;
    };
} */

With this transformation, UsedHere becomes a unified object type with each property being a single object type. The inclusion of prohibited?: undefined serves the same purpose as prohibited?: never, given that | undefined is automatically appended to any optional properties when --strictNullChecks is enabled.

Following these adjustments, the remaining code should compile without errors:

let x: UsedHere = {
    someField: {
        anotherField: ""
    }
}; // okay

Hopefully, this information proves useful. Best wishes as you continue working with TypeScript, and may you eventually transition to a newer version!

Access Playground Link for Code Execution

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

How can Jest be configured to test for the "permission denied" error?

In my Jest test, I am testing the behavior when trying to start a node http server with an invalid path for the socket file: describe('On any platform', (): void => { it('throws an error when trying to start with an invalid socket P ...

Encountering a ReactJS and TypeScript issue with error code TS2322: Unable to assign type to 'IntrinsicAttributes & IntrinsicClassAttributes'

I encountered a TS2322 error when trying to pass the searchForBooks method as props from the JumboBooks component to the SearchBooks component: JumboBooks.tsx (Parent) import { RouteComponentProps } from 'react-router'; ... export class JumboBo ...

Updating the DOM after making changes with Maquette involves calling the `renderMaquette

In a previous discussion, I expressed my desire to utilize Maquette as a foundational hyperscript language. Consequently, avoiding the use of maquette.projector is essential for me. However, despite successfully appending SVG objects created with Maquette ...

Searching for a specific document using AngularFirestore - what's the best method?

Is it possible to create an Observable that is limited to a single document? While the code provided creates an Observable for querying multiple documents: foo.component.ts import { AngularFirestore } from '@angular/fire/firestore'; import { O ...

Using Angular/Typescript to interact with HTML5 Input type Date on Firefox (FF)

Are there any Angular/Typescript projects that are completely built without relying on third-party libraries? I am encountering problems with Firefox and IE11. It works fine on Chrome where the value can be read, but the calendar does not display when us ...

Generate sample data within a fixture

Currently, I am in the process of working on a project that involves creating users and conducting tests on those users. To generate user data such as first name and last name, I am utilizing the faker tool. My goal is to create a user with these generated ...

Developing a unique TypeScript singleton pattern tailored for multiple PouchDB instances

I have developed a node application that interfaces with multiple databases. I've designed a class which allows me to create various databases effortlessly, as they share similar CRUD operations. The Class: class DatabaseService { private dbName: ...

Use JavaScript's Array.filter method to efficiently filter out duplicates without causing any UI slowdown

In a unique case I'm dealing with, certain validation logic needs to occur in the UI for specific business reasons[...]. The array could potentially contain anywhere from several tens to hundreds of thousands of items (1-400K). This frontend operation ...

Encountering the error "tsx is not defined" during a Jest test in a React/TypeScript project

I'm currently working on implementing Jest tests within a React project that has enforced TypeScript settings. In a simple test.tsx file located in the test folder, I have the following code: import React from 'react'; describe('Test& ...

The @Input() function is failing to display or fetch the latest value that was passed

I am currently working on an angular project, and I've encountered a situation where I'm attempting to send a value from a parent component to a child component using the @Input() decorator. Despite my efforts, the child component continues to di ...

The cancel function in lodash's debounce feature does not successfully halt the execution of the

In my angular application, I have implemented http calls on each modelChange event with the help of lodash's _.debounce(). However, I'm facing an issue where I am unable to cancel these calls after the initial successful execution of debounce. ...

The class variable cannot access the Angular Http response returned by the service

I have a Typescript application built with Angular 2. In this application, I need to retrieve Build Artifacts from a Jenkins server using the Jenkins Rest API. The Build Artifact contains a text file that I want to read from. I am making use of Angular&apo ...

Transformer Class: An object containing properties that are instances of another class

class ClassA { x: number; y: number; sum(): number { return this.x + this.y; } } class ClassB { @Type(() => ClassA) z: {[key: string]: ClassA}; } const b = transformObject(ClassB, obj); const z = b.z[key]; const s = z.s ...

`Inconsistencies in console.log output with Angular Firestore``

I'm currently working on retrieving the id of selected data, but when I test it using console.log, it keeps outputting twice. The image below illustrates the console.log output. https://i.stack.imgur.com/IARng.png My goal is to fetch the id once and ...

Unraveling the mysteries of Typescript with async await

I'm facing a peculiar issue in my code that I'm struggling to identify. try { const result = await somePromise.catch((err) => { console.log(new Date()); // displays time, t0 console.log('Stats', eventLoopStats.se ...

The compilation of the module has encountered an error with the PostCSS loader. There is a SyntaxError at line 2, character 14 indicating an unknown

I am developing an Angular 8 application. Currently, I am incorporating AlertifyJs into my project. In the styles.css file of Angular, I have imported these libraries: @import '../node_modules/alertifyjs/build/alertify.min.js'; @import '. ...

Utilizing the combineReducers() function yields disparate runtime outcomes compared to using a single reducer

Trying to set up a basic store using a root reducer and initial state. The root reducer is as follows: import Entity from "../api/Entity"; import { UPDATE_GROUPING } from "../constants/action-types"; import IAction from "../interfaces/IAction"; import IS ...

Removing a directory from GitHub with the help of octokit/rest

I am attempting to utilize octokit/rest in order to programmatically remove a directory. Below is the code I am using: import {Octokit as Github} from '@octokit/rest'; const githubToken = "read from vault"; // Functions for retrieving current c ...

"Sorry, there was an issue with AmStockCharts when trying to update the chart: Unable to assign a value to the '

Currently, I am using Angular 4.3.6 along with TypeScript 2.4.2 for my project. The issue that I am facing involves reading data from a socket and attempting to add it to the dataprovider. I came across an example at: While implementing a serial chart, q ...

Error: The argument provided cannot be assigned to a parameter that requires a string type, as it is currently a number

Currently, I am in the process of migrating some older websites to TypeScript. However, I keep encountering a type error during the build process. The specific error message is Type error: Argument of type 'number' is not assignable to parameter ...