Can we create a generic constraint that utilizes an index, be it a type or an object?

I am currently generating client models (Entities) along with their corresponding Primary Keys.

My goal is to create a method signature where, based on the Entity provided, the second parameter should be its Primary Key only.

The specific use of types and classes mentioned in the code snippet below may not be mandatory and could potentially be replaced by interfaces or constants for mapping purposes.

This is what I have attempted so far:

export type ClassType<T> = new (...args: any[]) => T

export class CustomerPk {
  customerId: number;
}

export class VendorPk {
  vendorId: number;
}

export class Customer implements CustomerPk {
  customerId: number;
  name: string;
}

export class Vendor implements VendorPk{
  vendorId: number;
  name: string;
}
  
export type EntityType = Customer | Vendor;
export type EntityPk = CustomerPk | VendorPk;

export type entityToPkMap = {
  Customer: CustomerPk, Vendor: VendorPk
}

To use it as follows:

constructor() {   
    const myCust = this.getData(Customer, new CustomerPk());
    const myVend = this.getData(Vendor, new CustomerPk());  // Intended to provide compile-time verification.
  }
  
  public getData<T extends EntityType, K>(entity: ClassType<T>, primaryKey: K): T {
    throw new Error('Not Implemented');
 }

I have experimented with different variations but have yet to achieve the desired outcome:

public getData<T extends EntityType, K extends entityToPkMap[T]>(entity: ClassType<T>, primaryKey: K): T

This results in an error stating "Type 'T' cannot be used to index type 'entityToPkMap'."

Answer №1

To handle the primary key type, one could utilize conditional types in TypeScript:

type PkMap<T> =
    T extends Customer ? CustomerPk :
    T extends Vendor ? VendorPk :
    never;

class Foo {
    constructor() {
        const myCust = this.GetData(Customer, new CustomerPk());
        const myVend = this.GetData(Vendor, new CustomerPk()); // expect error
    }

    public GetData<T>(entity: ClassType<T>, primaryKey: PkMap<T>): T {
        throw new Error('Not Implemented');
    }
}

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

I am experiencing difficulties with bringing in node modules into my project

Trying to incorporate @mui/styles into my React project resulted in encountering some errors as shown below. npm ERR! Could not resolve dependency: npm ERR! peer react@"^17.0.0" from @mui/<a href="/cdn-cgi/l/email-protection" class="__cf_email ...

Protractor Browser Instance Failure

We have encountered an issue with our UI suite failing in Chrome during the login process. Initially, we thought it might be due to upgrading to Chrome 79, as the problems arose simultaneously. Interestingly, the login functionality still works smoothly in ...

What are the issues causing trouble for my modules, services, and more in Angular ^17?

As I was going through the themes, I couldn't find a similar question. My issue revolves around Angular's inability to locate modules and services that are created using "ng g". Everything seems to be correctly set up, but errors or warnings keep ...

How can I utilize Angular services to transfer a count value to the Component?

I've been working on creating a coin counter for my application by developing a service specifically for counting coins. However, when I tried to use this service in one of my components where the count function is triggered, I encountered some diffic ...

Enhancing the efficiency of Angular applications

My angular application is currently coded in a single app.module.ts file, containing all the components. However, I am facing issues with slow loading times. Is there a way to improve the load time of the application while keeping all the components within ...

Combining 2 lists in Angular Firebase: A Simple Guide

I have been searching for a solution for the past 2 hours, but unfortunately haven't found one yet. Although I have experience working with both SQL and NoSQL databases, this particular issue is new to me. My problem is quite straightforward: I have t ...

Guidelines on incorporating emotion/styled into React applications with TypeScript

Including my root component in the ThemeProvider from @emotion/react has granted me access to props.theme. Here is an example: const StyledDiv = styled.div` background-color: ${(props) => props.theme.palette.primary.main}; `; Issue: TypeScript indica ...

How to dynamically set a background image using Ionic's ngStyle

I've been trying to set a background image on my card using ngStyle Take a look at my code below: <ion-slides slidesPerView="1" centeredSlides (ionSlideWillChange)= "slideChange($event)" [ngStyle]= "{'background-image': 'ur ...

Tips for using the arrow keys to navigate the cursor/caret within an input field

I am trying to create a function that allows the cursor/caret to move inside an input field character by character using the arrow keys (ArrowLeft, ArrowRight) on a keydown event. Current Approach: const handleKeyDown = (e: KeyboardEvent<HTMLInputEle ...

The serverTimeStamp() function in firebase.firestore.FieldValue does not allow for the Timestamp data type to be used

async addNewUser(id: string, email: string) { await this.afs.doc<MemberProfileModel>(FirestoreDbConstant.MEMBER_PROFILES + `/${id}`).set({ email, registeredDate: firebase.firestore.FieldValue.serverTimestamp(), }); } This appro ...

Debugger for Visual Code unable to locate URL in Microsoft Office Add-in

I recently installed the Microsoft Office Add-in Debugger VS code extension, but I'm having trouble getting it to work despite following the instructions. Every time I try, an error message pops up: https://i.sstatic.net/h2FYs.png Upon inspecting my ...

Error notifications continue to appear despite the presence of data in the input field

I am utilizing a component to exhibit various information (such as first name, last name, phone number, etc.) fetched from the API. The main focus is on executing CRUD operations, particularly the update operation. Referencing the image below: An is ...

Struggling to overcome the TS2322 error when assigning generic values

I am currently working on developing higher-order React components that will include default values for components labeled as "named". Here is a basic implementation example: type SomeProps = { a: string } type Variants = 'variantA' | 'var ...

Tips for securely accessing a parameterized property of an object in Typescript

I need to create a function that takes an object as an argument and accesses a specific property of this object based on another parameter. Here is the code snippet: // javascript code function setProperty(subject, property, value) { subject[property] ...

Performing unit testing on a Vue component that relies on external dependencies

Currently, I am in the process of testing my SiWizard component, which relies on external dependencies from the syncfusion library. The component imports various modules from this library. SiWizard.vue Imports import SiFooter from "@/components/subCompon ...

Submit a pdf file created with html2pdf to an S3 bucket using form data

Currently, I have the following script: exportPDF(id) { const options = { filename: 'INV' + id + '.pdf', image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 2, dpi: 300, letterRendering: true, useC ...

Exploring the traversal of an array of objects within Tree Node

How can I transform my data into a specific Tree Node format? Is there a method (using Typescript or jQuery) to iterate through each object and its nested children, grandchildren, and so on, and modify the structure? Current data format { "content" ...

Remix.js is unable to perform a redirect action when utilizing the Form component

I've been searching through the Remix documentation, but I can't seem to find a solution to my issue. It appears that you're unable to redirect from an action when using the Form component in Remix. You can check out this StackBlitz example ...

Easy steps for importing node modules in TypeScript

I'm currently navigating the world of TypeScript and attempting to incorporate a module that is imported from a node module. I have chosen not to utilize webpack or any other build tools in order to maintain simplicity and clarity. Here is the struct ...

Labeling src library files with namespaces

I have developed a ReactJS website that interacts with a library called analyzejs which was created in another programming language. While I am able to call functions from this library, I do not have much flexibility to modify its contents. Up until now, ...