Utilizing the value of a parent type in a different type in TypeScript: A guide

Currently, I am in the process of experimenting with creating my own basic ORM system. Below is the snippet of code that I have been working on:

type Models = {
   User: {
      name: string
   },
   Template: {
      text: string
   }
}

type ExtractKeysFrom<T> = keyof T

type ModelsKeys = ExtractKeysFrom<Models, Object>
// The expected output here is: 'User' | 'Template'

type ORM = {
   model: (modelName: ModelsKeys) => {
      create(props: Models[typeof modelName]): Promise<boolean>
   }
}

As for the implementation:

declare const orm: () => ORM;
orm().model('User').create({
  name: 'Adam'
})

I want the props parameter in the create() function to be valid and point only to properties of the User object. However, currently it shows:

create(props: User | Template): Promise<boolean>

I understand that using typeof modelName is incorrect in this scenario and it seems like I need to do some type checking with extends. Could you provide any advice on how to handle this situation properly?

Answer №1

It is my understanding that simply making the model function generic should solve your issue:

type ORM = {
   model: <T extends ModelsKeys>(modelName: T) => {
      create(props: Models[T]): Promise<boolean>
   }
}

In this case, the model name is defined as the type T and the return object containing the create function can utilize this to specify its parameter.

When testing this approach, it appears to meet your requirements:

declare const orm: ORM

orm.model('User').create({ name: 'Foo' }) // successful
orm.model('User').create({ text: 'Foo' }) // error

orm.model('Template').create({ text: 'Foo' }) // successful
orm.model('Template').create({ name: 'Foo' }) // error

Explore Typescript playground

Answer №2

It is important to define the model function as a generic function that automatically determines its type based on the parameter:

type Models = {
   User: {
      name: string
   },
   Template: {
      text: string
   }
}

type ExtractKeysFrom<T> = keyof T

type ModelsKeys = ExtractKeysFrom<Models>

type ORM = {
   model: <T extends ModelsKeys>(modelName: T) => {
      create(props: Models[T]): Promise<boolean>
   }
}

declare const orm: () => ORM;

orm().model('User').create({ name: 'name' }); // OK
orm().model('User').create({ wrong: 'name' }); // KO

Check it out in TypeScript playground

Answer №3

Is this what you were looking for? I've simplified things by focusing on the model function.

interface Models {
    User: {
        name: string;
    };
    Template: {
        text: string;
    };
}

function model<
    ModelName extends keyof Models,
    ModelArgs extends Models[ModelName]
>(model: ModelName) {
    // implementation

    return {
        create(props: ModelArgs): any {
            // implementation
        },
    };
}

model("User").create({ name: "Alice" });
// success

model("User").create({ text: "foobar" });
// error, 'text' property does not exist for User

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

Synchronizing Angular icons with HTML text

Presenting my HTML code <div class="transfer-link" *ngIf="showTransferLink" qa-name="transfer-link"> <a routerLink="/Transfers"> <mat-icon>sync_alt</mat-icon> <div> Transfer </div> ...

Reconstructing the complete pathway using object identifiers

Imagine I have a set of website routes represented by the object below: const routes = { HOME: "start", ACCOUNT: { HOME: "account", PROFILE: "profile", ADDRESSES: { HOME: "addresses", DETA ...

Nativescript encountered an issue while attempting to generate the application. The module failed to load: app/main.js

I'm currently experimenting with the sample-Groceries application, and after installing NativeScript and angular 2 on two different machines, I encountered the same error message when trying to execute: tns run android --emulator While IOS operations ...

What is the method for utilizing a function's input type specified as "typeof A" to output the type "A"?

Check out this example from my sandbox: class A { doSomething() {} } class B {} const collection = { a: new A(), b: new B() } const findInstance = <T>(list: any, nonInstance: T): T => { for (const item in list) { if (lis ...

Converting an array of arrays into an object with an index signature: A step-by-step guide

I find myself facing a challenge where I have two types, B and A, along with an array called "a". My objective is to convert this array into type B. Type A = Array<[string, number, string]>; Type B = { [name: string]: { name: ...

What could be causing the issue of CSS Styles not being applied to an Angular 2 component with Vaadin elements?

Currently, I am immersed in the tutorial on Vaadin elements using Angular 2 that I stumbled upon here In section 5.3, Styles are applied to the app.component.ts as shown below import { Component } from [email protected]/core'; @Component({ select ...

Steps for TS to infer types on interfaces

Incorporated in my React application is an object that I devised. Within this object, there is the following definition for Props: type Props = { message: MessageTypes | MessageImgTypes; showTimeStamp: boolean; } If we assume that MessageTypes consists o ...

Creating a Typescript version of the mongodb project aggregation functionality

Present scenario: I am currently working on creating a type-safe wrapper for the node-mongodb driver. I am facing challenges in determining the return type for the project aggregation stage. Feel free to check out the TypeScript Playground here class Base ...

Leveraging non-React entities to seamlessly integrate components within a component hierarchy in React utilizing TypeScript

I am currently working on a React Typescript project where I am exploring the use of traditional polymorphism. Below is a simplified version of my project, where components are returned from vanilla Typescript objects rather than React components, allowing ...

When utilizing a 'Token' in the provider() aliasing within Angular 2, the Typescript compiler may display an error message stating 'Unresolved variable or type'. This issue can arise when defining

When working with Typscript, I've encountered an issue where it can't handle a 'Token' in the context of an Angular2 provide() aliasing function. I'm unsure if there's a specific setting in the typescript compiler to address t ...

bespoke arguments for the super function in a subclass of Angular

I am attempting to incorporate the ol sidebar from umbe1987/Turbo87 into an Angular project. As I extend a class, I find myself needing to manipulate constructor parameters in the derived class constructor before passing them to the superclass constructor ...

Angular - Enabling the next screen button only after completing multiple selections

Currently, I'm working on a screen where users can select multiple options from a table. The requirement is that they must select at least 3 options before they can proceed. However, I am facing difficulties in implementing this functionality and unsu ...

Sharing data between components in Angular 4: Passing objects between different parts of your

Exploring Angular 4 development using TypeScript: I am looking to establish a static object in app.component.ts that can be accessed in all components. Any suggestions on how to accomplish this? ...

Exploring JSON data in real-time

My goal here is to utilize the variables retrieved from the route to determine which blog to access from the JSON file. The JSON file consists of an array of sections, each containing an array of blogs. Although the code works flawlessly when I manually s ...

Unlocking $refs with the Composition API in Vue3 - A step-by-step guide

I am currently exploring how to access $refs in Vue 3 using the Composition API. In my template, I have two child components and I specifically need to obtain a reference to one of them: <template> <comp-foo /> <comp-bar ref="ta ...

Error in Angular: Http Provider Not Found

NPM Version: 8.1.4 Encountered Issue: Error: Uncaught (in promise): Error: Error in ./SignupComponent class SignupComponent_Host - inline template:0:0 caused by: No provider for Http! Error: No provider for Http! The error message usually indicates the a ...

Resolving Incompatibility Problems Between Devices

While learning Typescript with React, I have encountered type compatibility issues when converting dates. Below is the content of my data.ts file: import { Result } from "./columns"; export enum Quality { High = "high", Medium = & ...

Transferring Cookies through FETCH API using a GET method from the client-side to the server-side

Struggling with a challenge here: Attempting to send a cookie via a GET request to determine if the user is logged in. The cookie is successfully transmitted to my browser and is visible in the developer tools. When I manually make a request through the UR ...

Tips for stopping webpack from creating compiled files in the source directory

I'm in the process of transitioning my AngularJs project from ES6 to TypeScript and I've integrated webpack with ts-loader. However, I've encountered an issue where the compiled files and source maps are saved in my directory instead of bei ...

Backend images are failing to load

I'm facing an issue where the image I send from a nestjs backend to an angular frontend isn't displaying in the browser. https://i.sstatic.net/nicu4.png Here's how it works: I make a request from the frontend to the backend with the file p ...