Typescript: Validate that a type includes property A when it contains property B

I have a type that is structured like so:

type MyType = {
  a: string;
  b: string;
  c?: number;
  d?: string;
}

Instances of this type can take different forms such as:

const myObj1: MyType = { a, b };
const myObj2: MyType = { a, b, c, d };

If an object of type MyType includes property c, then it must also include property d. Is there a way to define this type without needing non-null assertion or checking for both types, other than extending the type into a separate one?

Answer №1

In case you have the permission to modify MyType, a possible solution is to divide the c and d properties into a separate object where they are mandatory, and then switch with an intersection with that particular object.

type XY = {
    x: string;
    y: string;
};
type MyNewType = XY | XY & {
    c: number;
    d: string;
}

This methodology ensures that if an instance of MyNewType contains a c property, TypeScript will automatically infer the existence of a corresponding d property as well.

Answer №2

To ensure that property 'd' exists only when 'c' is defined and vice-versa, consider utilizing extended interfaces and overwriting optional properties as 'never'. Here's an example:

type Base = {
  x: string;
  y: string;
  z?: number;
  d?: boolean;
} 

interface Specific1 extends Base {
  z?: never;
  d?: never;
}
    
interface Specific2 extends Base {
  z: number;
  d: boolean;
}

type CustomType = Specific1 | Specific2;

const obj1: CustomType = { x: 'x', y: 'y' }; 👍
const obj2: CustomType = { x: 'x', y: 'y', z: 10 }; ❌
const obj3: CustomType = { x: 'x', y: 'y', z: 10, d: true }; 👍

This setup guarantees that an object of type CustomType will always have either x, y or x, y, z, d properties.

Check out the playground for more.

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

Exploring TypeScript's Conditional Types

Consider this scenario: type TypeMapping = { Boolean: boolean, String: string, Number: number, ArrayOfString: Array<string>, ArrayOfBoolean: Array<boolean> } export interface ElemType { foo: keyof TypeMapping, default: valueof T ...

How can I hide selected options in GraphQL playground?

I'm facing an issue in the playground with my view. When I try to add another option to select, pressing CTRL + space shows me every possible option, including the ones already selected. Is there a way to prevent this behavior? I only want to see the ...

Receive response after executing onFinalize Firebase cloud function

I have successfully created an unzip onFinalize function that unzips any file copied to storage and then deletes the file. However, I am looking for a way to receive a return value from the onFinalize cloud function in my Angular app or somehow listen for ...

Ways to properly assign a key in a Generic Interface as the interface key

Can someone assist me with TypeScript generics? I am wondering how to access the T["value"] field within the ActionAdd interface. type UserValue = { username: string; }; interface User { id: number; value: UserValue; } interface ActionAdd<T = unkn ...

Can anyone provide guidance on incorporating lodash into an Ionic 2 project?

Recently, I began diving into a new project that involves Ionic 2. TypeScript is still fairly new to me, and I've been brainstorming ways to integrate lodash into my project. Have any of you tackled this before and can offer guidance on how to achiev ...

Custom React component - DataGrid

Just starting out in the world of React and attempting to create a custom component with parameters. I'm curious about the correct approach for achieving this. Here's my current code snippet - how do I properly pass Columns, ajax, and datasourc ...

I have encountered an issue where I am unable to include any additional classes in my next.js 13 component that is displaying sanity data inside a portableText element

I've been experimenting with various methods to style my elements. Attempted solutions include creating a custom component and passing it to the PortableText element, as well as directly adding the component to the PortableText element. import { cli ...

Absolute file path reference in Node.js

I'm working on a Node.js project using WebStorm IDE. Here's the structure of my project: The root folder is named "root" and inside are 2 folders: "main" and "typings". The "main" folder has a file called "foo.ts", while the "typings" folder co ...

Interpret the string as a tuple, enum, or dictionary structure

A specific set of data is being received in my cloud function: let geison=`{ "message" : [{"something":1}, {"is":2} ,{"up":3}, {"today":4}] }` The objective is to extract the keys and values from each item. ...

When buttons are clicked within Angular Material's Card component, it automatically triggers the click event of the card itself

One of the challenges I'm facing is having a mat-card within a component template: <mat-card *ngFor="let p of products" (click)="viewProduct(p)"> <mat-card-actions> <button mat-stroked-button (click)="addProductToCart(p)"&g ...

Custom Pipe creates a mesmerizing infinite loop effect on images (blinking)

I have some data that needs to be displayed and it looks like this: https://drive.google.com/open?id=1Od-QC4xpfXXH4UgKDPkhkB90DQMUDAhV Here is the code snippet: <ion-grid *ngFor="let item of content | sortprogram: 'month'"> <ion-it ...

When working with TypeScript, it's important to note that an implicit 'any' type may occur when trying to use an expression of type 'string' to index a specific type

Currently, I'm attempting to transfer a custom hook used in Vue for handling i18n from JavaScript to TypeScript. However, I am encountering a persistent error message: An element is implicitly assigned the type 'any' due to an expression o ...

Determining the Type<> of a component based on a string in Angular 2

Can you retrieve the type of a component (Type<T>) based on a string value? For example: let typeStr: string = 'MyComponent'; let type: any = getTypeFromName(typeStr); // actual type ...

Websites experiencing horizontal scrolling functionalities

I have noticed that in my angular project, the website becomes horizontally scrollable when I log in. This only happens after logging in, and does not occur beforehand. I'm using angular calendars and Bootstrap for styling. What could be causing this ...

Connecting two divs with lines in Angular can be achieved by using SVG elements such as

* Tournament Brackets Tree Web Page In the process of developing a responsive tournament brackets tree web page. * Connection Challenge I am facing an issue where I need to connect each bracket, represented by individual divs, with decorative lines linki ...

Determine the generic types of callback in TypeScript based on the argument provided

There are numerous Stack Overflow questions that share a similar title, but it seems none of them address this particular inquiry. I'm in the process of developing a wrapper for an express RequestHandler that can catch errors in asynchronous handlers ...

Experimenting with Vuejs by testing a function that delivers a Promise upon the execution of the "Created" hook

In my Vuejs application, I have the following script written in Typescript: import { Foo, FooRepository } from "./foo"; import Vue from 'vue'; import Component from 'vue-class-component'; import { Promise } from "bluebird"; @Component ...

Is it possible to create an instance in TypeScript without using class decorators?

As per the definition on Wikipedia, the decorator pattern enables you to enhance an object of a class with additional functionalities, such as: let ball = new BouncyBall(new Ball()) The Ball object is adorned with extra features from the BouncyBall class ...

Uploading files from Angular to Spring Boot encounters an issue with multipart boundary rejection

I am facing a challenge in uploading form data from Angular to Spring Boot server. Basically, in Spring Boot, I define the following classes: data class Photo( val id: Long = 0L, val file: MultipartFile ) data class PostRequest( @field:Size(m ...

How to determine the frequency of a specific word in a sentence using Angular 5

I need help finding a solution to count how many times a word appears in sentences. Input: k = 2 keywords = ["anacell", "cetracular", "betacellular"] reviews = [ "Anacell provides the best services in the city", "betacellular has awesome services", ...