Produce every conceivable Boolean values within TypeScript data type

I am looking to create all possible configurations based on a given type.

type MagicGenerator<'withWishlist' | 'withAddToCart', PickerProps> = ??

Thus, the expected output of MagicGenerator should look like this:

type ExpectedResult =
  | ({
    withWishlist: true;
    withAddToCart: true;
  } & PickerProps)
  | ({
    withWishlist?: false;
    withAddToCart: true;
  } & PickerProps)
  | ({
    withWishlist: true;
    withAddToCart?: false;
  } & PickerProps)
  | ({
    withWishlist?: false;
    withAddToCart?: false;
  } & { [P in keyof PickerProps]?: never });

The crux of the matter is that I want PickerProps to default to never only when both withWishlist and withAddToCart are either false or not provided

I attempted to implement something along these lines

type MagicGenerator<Keys extends string, Props extends object> =
  | ({ [K in Keys]: true } & Props)
  | ({ [K in Keys]?: false; } & {[P in Props]?: never})

but it did not yield the desired outcome

type NotFullResult = {
    withWishlist: true;
    withAddToCart: true;
    pickerProp: any
} | {
    withWishlist?: false | undefined;
    withAddToCart?: false | undefined;
    pickerProp?: undefined
}

Answer №1

This code snippet is designed to fulfill your needs

interface SmartGenerator<Keys extends string, Props extends Object> {
  | ({ [K in Keys]?: boolean } & {[P in keyof Props]?: never})
  | ({ [K in Keys]?: false } & Props)
}

Check out this demonstration: here

Answer №2

To efficiently generate all possible combinations of keys and set them to true, we can leverage a previously discussed approach that involves reusing types. The initial step is to define a type called KeyCombos<T, O = T> that recursively generates key combinations based on input parameters.

type KeyCombos<T, O = T> = T extends infer U ? [T] | (KeyCombos<Exclude<O, U>> extends infer U extends any[] ? (U extends U ? [T | U[number]] : never) : never) : never;

Next, for each combination generated, we need to selectively assign the keys in each combination to true while setting the remaining keys to false through a distributive conditional type and intersection of mapped types:

type MagicGenerator<Keys extends string, T, Combos extends string[] = KeyCombos<Keys>> =
    | ((Combos extends Combos ? { [K in Combos[number]]: true } & { [K in Exclude<Keys, Combos[number]>]?: false } : never) & T)
    | ({ [K in Keys]?: false } & { [K in keyof T]?: never }) extends infer O
    ? { [K in keyof O]: O[K] }
    : never;

Including a case where all keys are false or not provided is essential for completeness. The use of

extends infer O ? { [K in keyof O]: O[K] } : never
serves to simplify the resulting type for better visibility in tooltips.

This generator can be utilized as shown below:

type Props = MagicGenerator<"withWishlist" | "withAddToCart", PickerProps>;

The example interface PickerProps offers a basis for testing purposes, with defined properties like foo, bar, and baz.

Note that this solution accommodates scenarios involving more than two keys, showcasing its flexibility and complexity. For cases restricted to only two keys, a hardcoded approach may suffice.

Link toPlayground


It's worth noting that while this solution may not be the most optimized or elegant, it provides a functional implementation. Future optimizations may further enhance its efficiency.

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

Result of Mongodb aggregation operation

I've created a Property controller : //Retrieve Properties By Type const getPropertiesByType = async (req: Request, res: Response) => { const { cities, type } = req.query; const citiesArr = typeof cities === 'string' ? cities.spli ...

Ways to extract data from a Dynamic Form Element

I'm working on a form that allows me to dynamically create new input fields. You can check out my code at: CodeSandBox of My Code My goal is to capture the value of each dynamically created input using formControl. Here is the code snippet: HTML: ( ...

Found inconsistent results when running a npm script globally versus inline

After running some tests, I discovered that tslint is functioning correctly when using the following command: tslint -c tslint.json --project tsconfig.json 'src/**/*.ts' However, when attempting to integrate it into an npm script, it appears th ...

Having difficulty casting the parameter type from Array.find() in TypeScript

In my codebase, I am dealing with the OrganisationInterface type: export declare interface OrganisationInterface { documents?: { [documentType: OrganisationDocumentTypesList]: { // enum id: string; name: string; ...

Deployment of a NextJS14 app to Vercel encountered an issue: Unexpected token '<' found in JSON at position 0

Here is the issue at hand: next: 14.1.4 next-auth: 4.24.7 node version: 20 This is the structure of my authentication folder: No errors occur when running npm run dev I've been investigating this issue for three days, but I am still stuck. I belie ...

I'm looking to filter this array based on the value of a subarray that the user will specify the key and value for. How can I accomplish

Given the input var key="value_0" and var input="hello", I need to filter the array in TypeScript based on these values. The filtering criteria involve checking if the array elements contain a subarray with key="value_0" and if the value of this key includ ...

What is the best way to populate an Angular variable in Ionic following a subscription?

Currently, I am in the process of retrieving data from a server and displaying it on an Ionic page. I have successfully fetched the data without any issues and verified it in the console. However, how do I proceed once the server returns the data to me? T ...

The NgModel function within *ngFor is executing more times than necessary during initialization

Displayed on screen are a list of tutorials with check boxes next to each tutorial's states. These tutorials and states are pulled from the database, each tutorial containing a name and an array of associated states. Here is the HTML code: <div c ...

Adding attributes to parent DOM elements of a component in Angular2: A Step-by-Step Guide

I'm working with the following code: ... <div class="container"> <div class="fancy"> <fancybutton></fancybutton> </div> <button (click)="addAttribute()">Remove</button> <button (click)="remAttr ...

Error: Select dropdown placeholder malfunctioning

Even after trying numerous solutions from various forums, I am unable to make the placeholder display in my code. Maybe a fresh perspective can help spot what I might be missing. view image here I have experimented with using "" as the value, as ...

Error with Background component in Next.js-TypeScript when trying to change color on mouseover because Window is not defined

Within my Background component, there is a function that includes an SVG which changes color upon mouseover. While this functionality works fine, I encountered an error when hosting the project using Vercel - "ReferenceError: window is not defined." This i ...

The function http.get() will not give back an observable object

NOTE: The issue lies in the ionViewDidLoad() function not being executed, as the http.get method does return an observable. I am attempting to receive the observable when making a request to later retrieve its json response. However, I am not encountering ...

Encountering an issue with Nuxt 3.5.1 during the build process: "ERROR Cannot read properties of undefined (reading 'sys') (x4)"

I am currently working on an application built with Nuxt version 3.5.1. Here is a snippet of the script code: <script lang="ts" setup> import { IProduct } from './types'; const p = defineProps<IProduct>(); < ...

The onInit Observable subscription will only execute a single time

Within my table, I have a list of names and an input tag that filters the content of the table when its value changes. The data is retrieved from an HTTP request to a service. I am encountering three different scenarios: 1- If I subscribe to this.ds.getD ...

Error in TypeScript when accessing object using string variable as index

Currently, I am facing a challenge in my project where I am dynamically generating routes and managing them in an Elysia(~Express) application. The issue arises when TypeScript's type checking system fails to index an object using a string variable. S ...

The ultimate guide to leveraging the power of Vitejs React TS template

When I try to specify absolute paths in the 'vite.config.ts' file, Vite seems to be unable to read the path properly and throws an error in the console. // vite.config.ts // Libraries import { resolve } from 'path' import { defineCo ...

Do TypeScript project references provide value when noEmit is used?

To enhance the speed of my editor interaction and reduce the time taken by tsc to run on my TypeScript code, I am considering implementing project references. Many teams have reported substantial performance improvements after incorporating project referen ...

Increasing the number of service providers in Angular2-4 directives

Is there a way to apply both * to a string? Below is the code snippet I am working with: <a class="sidenav-anchor" *ngIf="!item.hasSubItems()" md-list-item md-ripple [routerLink]="[item.route]" routerLinkActive="active" [routerLinkActiveOptions]="{ex ...

On mobile devices, Tailwind CSS prioritizes larger screens over smaller screens when applying styles

Encountering an issue where the custom 2lg:/ lg: screens are conflicting with the md: screen in my React app. Even though the screen is set correctly to md:, it gets overwritten by the custom screens. Refer to the screenshot in "inspect" for a clearer view ...

What are some strategies to avoid losing form data while switching between components without refreshing the page?

I am looking for a solution to seamlessly swap between two components, each containing a form, while retaining the data inputted by the user without submitting. This functionality is similar to switching tabs in simple HTML. My approach involves using a v ...