Defined interface with specific number of members

I am tasked with creating an interface that has only two members, one of which is optional and both have undefined names. Something like:

interface MyInterface {
    [required: string]: string|number
    [optional: string]?: string|number
}

Unfortunately, this approach does not work due to indexed types allowing an undefined number of properties, resulting in a

Duplicate index signature for type 'string'
error. However, I believe it effectively conveys what I am trying to accomplish. I have yet to find a solution to achieve this, if it's even possible.

Use Case

This scenario involves a DynamoDB context where an item can fall into one of two categories: one with just a primary key acting as a unique identifier, and the other with a combination of primary and secondary keys that together form a unique identifier.

// Input with a single primary key
User = {
    email: "user@email", // primary key
    ... 
}

// Item with primary and secondary keys
Post = {
    title: "Post Title", // primary key
    author: "user@email", // secondary key
    ...
}

To retrieve the first item, we use:

get({ email: "user@email" }) {
    // do something with this input
}

For the second item, we use:

get({ title: "Post Title", author: "user@email" }) {
    // do something with this input
}

We need the get() function to accept both scenarios without knowing the actual names of the primary or secondary keys.

Current Implementation

Currently, the get() function accepts input in the following format:

interface Input {
    PrimaryKey: string|number
    SecondaryKey?: string|number
}

get({ PrimaryKey: "user@email" }: Input) {
    // Retrieves the key name by querying the table.
}

get({ PrimaryKey: "Post Title", SecondaryKey: "user@email" }: Input) {
    // Retrieves the pair names by querying the table.
}

While this method works, using generic terms like PrimaryKey and SecondaryKey instead of the actual key names can lead to confusion easily.

Answer №1

It seems unusual to me that Typescript would be responsible for keeping track of the number of properties. Perhaps a tuple could provide a more efficient solution? Consider implementing something like this:

interface Item {
  key: string,
  value: string | number
}
type Items = [Item] | [Item, Item]

You can then create a helper function for property access:

const getPropertyValue = (items: Items, targetKey: string): string | number | undefined =>
  items.find((item) => item.key === targetKey)?.value

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

Next.js Version 13 - Unable to find solution for 'supports-color' conflict

Currently in the midst of developing a Next.js 13 app (with TypeScript) and utilizing the Sendgrid npm package. An ongoing issue keeps popping up: Module not found: Can't resolve 'supports-color' in '.../node_modules/debug/src' ...

The data type 'boolean' cannot be assigned to the type 'CaseReducer<ReportedCasesState, { payload: any; type: string; }>'

I recently developed a deletion reducer using reduxjs/toolkit: import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { AppThunk } from "../store"; import { ReportedCase, deleteReportCase } from "../../api/reportedCasesApi"; import history ...

Collect the GET parameters as an array of strings when there is only one value

How can I properly pass a string array as a parameter for a GET call? // Passing one value param: filters=Something value: filters: 'Something' // Passing multiple values param: filters=Something&filters=Something else value: filters: [ &ap ...

No routes found that match. URL Segment 'calendar' does not correspond to any routes available

Currently interning, I've been tasked with building my own Angular 5 web application. However, I've hit a roadblock with an issue that's had me stuck for hours now. Every time I try to access the calendar, it gives me an error saying it can& ...

Creating a higher order component (HOC) that utilizes both withRouter and connect functions in React

I am currently working with the following stack: <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="87f5e2e6e4f3c7b6b1a9b6b4a9b6">[email protected]</a> <a href="/cdn-cgi/l/email-protection" class="__cf_email__" dat ...

"Unindexing data in Angular: A step-by-step guide

Can someone help me figure out how to delete an item by index in Angular? I have a parameter and a remove button, but when I tried putting my parameter inside the remove button it didn't work. How can I fix this? deleteRowFiles(rowIndex: number){ th ...

Using a nodejs module is causing an error in my code

I am dealing with a module like this: module Net.Server { var socket:dgram.Socket; [...] } Here is my app.ts file: var server:Net.Server = new Server(); However, when I include this line at the beginning of the first file: import dgram = requ ...

Order of Execution

I am facing an issue with the order of execution while trying to retrieve values from my WebApi for input validation. It appears that the asynchronous nature of the get operation is causing this discrepancy in execution order. I believe the asynchronous b ...

Angular Typescript filter function returning an empty arrayIn an Angular project, a

I have a filtering function in Angular that is returning an empty array. Despite trying similar solutions from previous questions, the issue persists. The function itself appears to be correct. Any assistance would be greatly appreciated. gifts represents ...

Guide to uploading a recorded audio file (Blob) to a server using ReactJS

I'm having trouble using the react-media-recorder library to send recorded voice as a file to my backend. The backend only supports mp3 and ogg formats. Can anyone provide guidance on how to accomplish this task? Your help would be greatly appreciated ...

How can I get rid of the table borders and set colors for every other row in the

How can I remove the border lines from a table and assign colors to alternate rows in the table? Follow this link for the code: https://stackblitz.com/angular/kooxxyvddeqb?file=app%2Ftable-sticky-columns-example.css Thank you in advance ...

Modeling a potentially empty array in Typescript can be achieved by implementing specific interface definitions

Here is the current situation: type A = { b: string, c: number } I have an object that I will receive from an API, which could be either A[] or [] As of now, when I attempt to use it, const apiData: A[] || [] const b = apiData[0].a // I expected this to ...

The function has been called but it did not return a

It seems that there is confusion surrounding the .toHaveBeenCalled() Matcher in Jasmine. While it should return a Promise that resolves when the function has been called, some users are experiencing it returning undefined instead. For example: it('sh ...

Error: Property 'mytest' is undefined and cannot be read

While working with Swagger API, I encountered an error message when calling the endpoint stating "Cannot read property 'mytest' of undefined" class UserData { private mytest(req:any, res:any, next:any){ return res.json('test32423423&a ...

Is there a way to upload a file and FormData simultaneously without storing the file on the server's disk?

When it comes to uploading files and FormData to a server, I found a method that works well: On the client side, I am using Angular 2 with the following logic: 1. In the component onLoadForeignLightCompanies(event: any) { let fileList: FileList = ev ...

What are the consequences of relying too heavily on deep type inference in React and Typescript?

In the process of migrating my React + Javascript project to Typescript, I am faced with preserving a nice unidirectional flow in my existing code. The current flow is structured as follows: 1. Component: FoobarListComponent -> useQueryFetchFoobars() 2 ...

Angular8 with the [tinymce] library for customizing editor elements and configuring multiline options

I am currently working with Angular 8 and in the template, we have the following code snippet: <editor required class="research-modal__control__input research-modal__control__input__description" formCo ...

Exploring ways to list interface keys in order to create a new interface where the value is determined by the corresponding key

How can we iterate through interface keys to create a new interface where the value is dependent on the key? type IParse<T> = { [K in keyof T as K extends string ? K : never]: string // How can we specify that if K === 'a', the type sho ...

Issues with Webpack and TypeScript CommonsChunkPlugin functionality not functioning as expected

Despite following various tutorials on setting up CommonsChunkPlugin, I am unable to get it to work. I have also gone through the existing posts related to this issue without any success. In my project, I have three TypeScript files that require the same ...

Error: Property 'xxx' is not a valid attribute for this type

Hey there! I recently converted my React Native JavaScript project into TypeScript and everything seems to be working fine. However, I'm encountering some warnings that I could use some help with. Specifically, I need assistance on how to properly pas ...