Distributing tuples while also implementing optional features

Is it possible to modify the code snippet below so that Test2 outputs: [string, boolean?, ...string[]] while taking into account the optional field?

type Def = { type: any, spread: boolean, optional: boolean }
type A = { type: string,   spread: false, optional: false }
type B = { type: boolean,  spread: false, optional: true  }
type C = { type: string[], spread: true,  optional: false }
type D = { type: number,   spread: false, optional: false }

type ArrayBuilder<
  T extends Def[],
  A extends any[] = [],
  B extends any[] = [],
  C extends any[] = [],
  State extends 'A' | 'B' = 'A',
> = T extends [
  infer H extends Def,
  ...infer R extends Def[],
] ? State extends 'A' ? H['spread'] extends true ? ArrayBuilder<R, A, H['type'], [], 'B'> : ArrayBuilder<R, [...A, H['type']], [], [], 'A'>
  :ArrayBuilder<R, A, B, [...C, H['type']], 'B'>
  : [...A, ...B, ...C]

type Test1 = ArrayBuilder<[A,C,D]> // [string, ...string[], number]

// Can the code above be modified, such that Test2 produces: [string, boolean?, ...string[]] by factoring in the optional field?
type Test2 = ArrayBuilder<[A,B,C]> // [string, boolean, ...string[]] - should become [string, boolean?, ...string[]]

To apply the spread, I'm using [...A,...ItemToSpread], but to apply the optional attribute, I must use {[I in keyof T]?: T[I] } - which doesn't work well with spreads.

code

Answer №1

To ensure proper functionality, always verify the presence of H["spread"] and H["optional"] before assigning H["type"] to the ArrayBuilder:

type ArrayBuilder<
  T extends Def[],
  A extends any[] = [],
  B extends any[] = [],
  C extends any[] = [],
  State extends "A" | "B" = "A"
> = T extends [infer H extends Def, ...infer R extends Def[]]
  ? State extends "A"
    ? H["spread"] extends true
      ? ArrayBuilder<R, A, H["type"], [], "B">
      : H["optional"] extends true ? ArrayBuilder<R, [...A, H["type"]?], [], [], "A"> : ArrayBuilder<R, [...A, H["type"]], [], [], "A">
    : H["optional"] extends true ? ArrayBuilder<R, A, B, [...C, H["type"]?], "B"> : ArrayBuilder<R, A, B, [...C, H["type"]], "B">
  : [...A, ...B, ...C];

If you have activated the exactOptionalPropertyTypes setting, you will achieve the desired outcome for Test2:

type Test2 = ArrayBuilder<[A, B, C]>; // [string, boolean?, ...string[]]

Explore further on the Playground

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

The navigation bar is struggling to be positioned on top of the body

I have encountered an issue where I want my navbar to remain on top of all components, but when I open the navigation menu, it pushes all the components of the index page down. My tech stack includes Next.js, Tailwind CSS, and Framer Motion. This problem ...

Exporting items with a label in TypeScript/JavaScript

Is it possible to rename the functions that are exported using the following syntax in Typescript/Javascript? export const { selectIds, selectEntities, selectAll, selectTotal } = adapter.getSelectors(selectState); I would like to import selectAll as sele ...

When I select a link on the current page, I would like the information in the input fields to be cleared

Currently using Angular 8, I recently included onSameUrlNavigation: 'reload' to my router. This change has successfully allowed the page to reload upon a second click on the same link. However, I've noticed that the input fields on the reloa ...

Subscription to Observable content failed to run

When a submit button is clicked inside the component HTML, it triggers a function called addCollaborators(). The code for this function can be found below: component.ts emails: string[] = []; constructor(public userService: UserService) {} // Function ...

Tips for determining the minimum value within an array of objects across multiple keys using a single function

I am currently tasked with the challenge of determining the minimum value from an array of objects that contain multiple keys. My ultimate goal is to identify the minimum value among all keys or specific keys within the objects. For instance var users = ...

Angular 2+ encountering an internal server error (500) while executing an http.post request

Here is my service function: public postDetails(Details): Observable<any> { let cpHeaders = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: cpHeaders }); return this.htt ...

Adding a fresh element to an object array in TypeScript

How can we add a specific value to an array of objects using TypeScript? I am looking to insert the value 1993 into each "annualRentCurrent" property in the sample object. Any suggestions on how to achieve this in TypeScript or Angular? Thank you! #Data ...

Struggling to narrow down the type of an object property even after verifying it with a type guard

Flavor is a distinct union, represented as a value of an Object. While attempting to execute this idea, it functions in js, however, TypeScript does not approve. ts playground link Desired Outcome: For TypeScript to comprehend discriminated unions within ...

Create a new object by mapping values from an array of two objects in Angular using TypeScript, based on the object

Here is a code snippet for a Question and Answer data structure: export class Question { id: string; title: string; description: string; answers: Answer[]; } export class Answer { id: string; text: string; questionId: string; } We have two ...

The value of additionalUserInfo.isNewUser in Firebase is consistently false

In my application using Ionic 4 with Firebase/AngularFire2, I authenticate users with the signinwithemeailandpassword() method. I need to verify if it's the first time a user is logging in after registering. Firebase provides the option to check this ...

What are some strategies for encouraging tools to embrace TypeScript's exhaustiveness checking with minimal reliance on comments?

My coding style involves incorporating exhaustiveness checking in a lot of the code I write. In the following code snippet, I intentionally introduce a type error in the line with _exhaustivenessCheck if there are additions made to the UnitOfTime union. W ...

React - Component not updating after Axios call in separate file

Recently I decided to delve into React while working on some R&D projects. One of my goals was to build an application from scratch as a way to learn and practice with the framework. As I started working on my project, I encountered a rather perplexin ...

Angular: Retrieving static values in a component post assignment

I have a constant array of orders declared in the constants.ts file export const ORDERS = [ { 'id': 'PROCESSING', 'displayName': null }, { 'id&a ...

updating a property value with retrieved data from an API before sending it to a nested component within an Angular application

Within a parent component, I am receiving data from an API, which is an Object with various properties. The specific property I want to pass to a child component is called "structure". Using Renderer2, I aim to add a class based on the value of this "struc ...

What is the best method for displaying file size in a user-friendly format using Angular 6?

Imagine having this snippet in an HTML file: *ngFor="let cell of dateFormat(row)">{{cell | filesize}}</td>, where the dateFormat function looks like this: dateFormat(row:string){ var today = new Date(row[4]); let latest_date = this.date ...

How to empty an array once all its elements have been displayed

My query pertains specifically to Angular/Typescript. I have an array containing elements that I am displaying on an HTML page, but the code is not finalized yet. Here is an excerpt: Typescript import { Component, Input, NgZone, OnInit } from '@angul ...

"Omitting the parameter value when passing it to a directive in Angular

I recently developed a Directive in Angular7, but I encountered an issue when trying to pass a string value from the HTML to the directive. When using the following code snippet in my HTML: <ng-template [appValidatePermission]='CreateRole'&g ...

Having trouble with Angular 2 @input binding?

Parent module: import {NgModule} from '@angular/core'; import {SharedModule} from "app/shared/shared.module.ts"; import {HeaderComponent} from './header.component'; import {UserinfoComponent} from './userinfo.component'; imp ...

Troubleshooting Angular4 and TypeScript Compile Error TS2453: A Comprehensive

I'm facing an issue in my Angular4 project build process which I find quite perplexing. The error seems to be related to the import of certain components such as Response, Headers, and Http from @angular. Whenever I attempt to build my project, it thr ...

The module 'DynamicTestModule' experienced an import of an unexpected value under the name 'SohoComponentsModule'

I have been working on an angular 2 application using our UI team's library. The progress has been smooth, thanks to the easy integration of their components through import statements in my app.module.ts: import { BrowserModule } from '@angular/ ...