What is the best way to form a new type that encompasses all shared properties found within a union of types?

Is there a method to safely map over the union of arrays without hard-coding specific types?

When attempting to calculate newArr1, an error is encountered:

Property 'field2' does not exist on type 'Common<A, B>'
. How can this error be replicated for newArr2 as well?

(link to code)

interface A {
    field1: string
    field2: number
}
interface B {
    field1: string
}

type Common<A, B> = {
    [P in keyof A & keyof B]: A[P] | B[P];
}

function mapArray(arr: A[] | B[]) {

    const newArr1 = (arr as Common<A, B>[]).map(i => i.field2) // error

    // how can I get the same error without hard-coding the types from the type union?
    const newArr2 = (arr as MagicEventuallyFromJcalz<typeof arr>).map(i => i.field2)

    return newArr1
}

Answer №1

Shoutout to jcalz and William Lohan for their valuable input!

Here's an interesting scenario: when making 2 separate requests to an external API, I receive distinct responses:

  1. An array containing detailed information about each user,
  2. An array with a condensed set of details compared to the previous one.

I wanted to extract users' IDs (since 'id' is a shared property) using a single function that could handle both types of arrays. With insights from jcalz's feedback, I managed to achieve this goal without explicitly specifying array types within the function. Kudos to jcalz for helping me figure it out! If you provide an answer, I'll gladly mark it as accepted.

In case you're curious, here's the approach I took (link to code):

interface DetailedUser {
    id: number
    many: number
    other: string
    fields: boolean
}
interface CompactUser {
    id: number
}

type Common<T> = Pick<T, keyof T>

type UnpackedFromArray<T> = T extends (infer U)[] ? U : never

function getUserIdsFromApi(usersJsonFromApi: DetailedUser[] | CompactUser[]) {

    // The lines below demonstrate that the function correctly triggers a TypeScript error,
    // asserting that the types are derived dynamically based on the 'usersJsonFromApi' variable.

    const userIds1 = (usersJsonFromApi as Common<UnpackedFromArray<typeof usersJsonFromApi>>[]).map(i => i.other)

    const userIds2 = (usersJsonFromApi as Common<typeof usersJsonFromApi[number]>[]).map(i => i.other)

    return userIds1
}

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

Converting strict primitive types to primitive types in Typescript

I have a function that parses a string into a value and returns a default value if it fails. The issue is that this code returns too strict types for primitives, such as `false` instead of `boolean`. How can I resolve this? Should I utilize some form of ...

Fastify Typescript: dealing with an unidentified body

I'm new to Fastify and I've encountered a problem with accessing values in the body using Typescript. Does anyone have any ideas or suggestions? Thanks! Update: I want to simplify my code and avoid using app.get(...) Here's my code snippet ...

Turn off the touch events system for Ionic 2 on the leaflet map's draw controller

Seeking guidance on how to disable data-tap functionality in Ionic 2 within a leaflet map div. Anyone familiar with this? In Ionic-v1, the solution involved adding data-tap-disabled="true" to the map container (ion-content). I recently integrated the lea ...

Is there a way to switch the eventHandler assigned to a particular input element dynamically?

I am facing a dilemma with my child component, which dynamically generates input fields within a parent component. <app-xxx *ngFor="let el of fieldsElements" [ngModel]="fieldsElements[el.name]" ... ... (keydown)="my ...

Parse the local JSON file and convert it into an array that conforms to an

My goal is to extract data from a local JSON file and store it in an array of InputData type objects. The JSON contains multiple entries, each following the structure of InputData. I attempted to achieve this with the code snippet below. The issue arises ...

typescript - add a global library import statement to every script

Recently, I began working on a TypeScript project in Node.js. I am looking to add import 'source-map-support/register'; to all of my .ts files for better visibility of TS source in stack traces. Is there a method to implement this without manuall ...

React - Ensure useEffect is triggered only after state update

One of my components (ItemsIndex) is using a custom hook to fetch data from our API. However, the ItemsIndex's useEffect runs first, causing the DOM to not be filled with elements that could be scrolled into view. How can I make sure that the useItems ...

Pause until the user selects either the confirm or deny option before proceeding with the next action

As a beginner in Angular, I am seeking help with my code structure. I have three files: WarningComponent (which displays a warning modal using Bootstrap), modalService (responsible for opening modals), and votingComponent. Within the votingComponent, ther ...

Issue with Readonly modifier not functioning as expected in Angular/Typescript

My goal is to create a component property that is read-only. However, I am facing an issue where the readonly modifier does not seem to have any effect. View example on stackblitz According to the documentation, once I initialize the cars property in the ...

Initial position of the range slider in IONIC 2

I have been searching the web extensively to find a solution to this particular issue. I am working with a range slider and trying to set its default starting values, but so far, I haven't had any luck. I've checked both the official documentatio ...

Unlocking the Potential of Vue Class Components: Exploring Advanced Customization Options

Currently, I am working on a project using Vue 2 with Typescript. However, I am facing an issue where I cannot add options to the component. <script lang="ts"> import { Component, Vue } from "vue-property-decorator"; import HelloW ...

Shifting the use of @Inject(MAT_DIALOG_DATA) away from class constructors

Our team is making a transition in the Dependency Injection pattern we utilize to minimize the dependency on TypeScript constructors. This shift will help us address recurring issues caused by team members adding logic that shouldn't be included in co ...

Dynamically apply classes in Angular using ngClass

Help needed with setting a class dynamically. Any guidance is appreciated. Below is the class in my SCSS file: .form-validation.invalid { border: 2px solid red } In my ts file, there's a variable named isEmailValid. When this variable is set to ...

The Angular2 view is failing to display updated data from a shared service

I've been struggling to show data from my shared service, but it's not displaying. Can someone please help me out? I've been stuck on this for the past few days. I've tried NgZone and ChangeDetectorRef, but they haven't worked for ...

Guide on how to showcase the template by leveraging the roomList information with ngTemplateOutlet in Angular

TS roomList = [{ name: 'Room2' }] HTML <div class="Layout-body"> <ng-container *ngFor="let dt of roomList; index as i" [ngTemplateOutlet]="Room1" [ngTemplateOutletContext]="{ data: dt, i: i }&qu ...

What are the steps for transforming my 2D array to fit a specific schema using RxJS?

UPDATE I stumbled upon a potential solution that I have appended to my question and am now seeking a more refined approach. In the context of an Angular 9 application, I am working with a two-dimensional array that I need to restructure. Through my use of ...

Cropping and resizing images

Within my angular application, I have successfully implemented image upload and preview functionality using the following code: HTML: <input type='file' (change)="readUrl($event)"> <img [src]="url"> TS: readUrl(event:any) { if ...

Displaying grouped arrays efficiently in Angular

I have received data from an API in the form of an array with objects structured like so: [ {"desc":"a", "menu": 1},{"desc":"b", "menu": 2},{"desc":"c", "menu": 1}, ...

Unexpected behavior observed in ng-select when pasting search values

When attempting to update an array of strings acting as the model for an ng-select, the values do not appear correctly in the search box. https://i.sstatic.net/WqdJ6.png The values that are displaying correctly are the ones selected from the dropdown men ...

When you find that the plugins on pub.dev do not offer web support, consider utilizing npm packages for Flutter web development

I am currently working on developing a cross-platform app using Flutter for iOS, Android, and web. However, some plugins do not support web. Fortunately, I came across npm packages that provide the same functionality and I am considering integrating them. ...