Type constraints on arguments in Typescript functions

I've been struggling with this issue for quite some time,

function processEntity<
  T extends Record<string, unknown>,
  U extends keyof T = keyof T,
  V extends Pick<T, U> = Pick<T, U>
>(arg: {keys: Array<U>; resolver: (doc: V) => void}) {
  arg.resolver(...)
}

type Cat = {
  name: string
  age: number
}

processEntity<Cat>({
  keys: ['name'],
  resolver: (doc) => {
    // doc.name should exist
    // doc.age should be undefined
  },
})

As shown above, there is a function called processEntity that takes an object as an argument.

My goal is to have the

type of the argument in arg.resolver
depend on the type of arg.keys. For example, if I pass ['name'] to the keys: field, then doc.age should not be accessible because 'age' was missing in the keys field.

I have looked at some related questions listed below but they have not been helpful, so please provide assistance :pray:

  • How to define a function's argument type dependent on string argument in Typescript?
  • Typescript make one parameter type depend on the other parameter
  • Declaring dependent argument types for optional arguments with conditional types
  • Typescript. Correctly typing function parameter that depends on property in the same object literal

Answer №1

You are on the right track. The key issue here is that Typescript does not offer support for partial inference within functions. This essentially means that you have to either specify all type parameters or allow Typescript to infer all of them - there is no middle ground where you can specify some and let TS figure out the rest. Specifically, you cannot define T and expect TS to infer U.

Fortunately, there are a few workarounds to address this limitation. One approach is to employ function currying to define T in the initial call and then let TS infer U in the subsequent call:

function processEntity<
    T extends Record<string, unknown>>() {
    return function <
        U extends keyof T = keyof T
    >(arg: { keys: Array<U>; resolver: (doc: Pick<T, U>) => void }) {
        //   arg.resolver(...)
    }
}

Playground Link

Alternatively, you can introduce a dummy field to serve as an inference point for T, even though the actual value assigned to it is irrelevant:

function processEntity<
    T extends Record<string, unknown>,
    U extends keyof T = keyof T,
    >(arg: { type: T, keys: Array<U>; resolver: (doc: Pick<T, U>) => void }) {
    //arg.resolver(...)
}

Playground Link

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

Prevent modal from closing when clicking outside in React

I am currently working with a modal component in react-bootstrap. Below is the code I used for importing the necessary modules. import React from "react"; import Modal from "react-bootstrap/Modal"; import ModalBody from "react-bootstrap/ModalBody"; impor ...

Tips for associating an id with PrimeNg menu command

Within my table, I have a list of items that I would like to enhance using PrimeNg Menu for dropdown menu options. The goal is to enable navigation to other pages based on the selected item id. When a user clicks on a menu item, I want to bind the id of th ...

Is Typescript capable of converting ES6 code to ES5 during transpilation?

Currently, I'm in the process of developing an application utilizing Angular 2 and TypeScript. My goal is to incorporate a JavaScript method, specifically 'filter' for arrays, that is compatible with IE 11+, Chrome 45+, and other similar bro ...

Creating a String Array and linking it to an Input Field

I'm currently working on a code that involves mapping through an array of strings using observables. My objective is to display the value from this array inside an input field. However, despite being able to view the array in the console, I encountere ...

Is there a way to import a module generated by typescript using its name directly in JavaScript?

I am trying to bring a function from a typescript-generated module into the global namespace of JavaScript. The typescript module I have is called foo.ts: export const fooFn = (): string => { return "hello"; }; Below is the structure of my HTML file ...

Establishing a pair of separate static directories within Nest

I am looking to utilize Nest in order to host two static applications. Essentially, I have a folder structure like this: /public /admin /main Within my Nest application, I currently have the following setup: app.useStaticAssets(join(__dirn ...

Altering the properties of a specified element within TestBed using the overrideComponent method

We are implementing TestBed.overrideComponent() to substitute a component with custom behavior. TestBed.overrideComponent(CoolComponent, { set: { template: '<div id="fake-component">i am the fake component</div>', sel ...

Elements constrained by themselves in a rest parameter with generic types

When using Typescript, it is possible to infer tuple types for generic rest parameters that are constrained by an array type. However, in my specific case, this functionality does not seem to work as expected. I am attempting to pass a series of pairs co ...

Configuring eslint-import-resolver-typescript in a multi-package repository

I'm currently working on implementing path-mapping within a monorepo structure. Despite having existing eslint-plugin-import rules in place, I am encountering an error stating "Unable to resolve path to module" for all mapped imports. app/ ├─ pack ...

Transform JSON into a TypeScript interface with a specialized Date method

Within my Angular 7 project, there is a Post Model defined as follows: export interface PostModel { id: number; created: Date; published: boolean; title: string; } I have implemented an Angular service method aimed at retrieving posts: public g ...

What is the source of the compiler options in tsconfig.json?

Currently utilizing Typescript in NestJs, I have incorporated various packages. However, the specific package responsible for altering these settings remains unknown to me: "checkJs": false, "skipLibCheck": true Is there a method to ...

Analyzing past UTC date times results in a peculiar shift in time zones

When I receive various times in UTC from a REST application, I encounter different results. Examples include 2999-01-30T23:00:00.000Z and 1699-12-30T23:00:00.000Z. To display these times on the front end, I use new Date(date) in JavaScript to convert the ...

Testing NestJS Global ModulesExplore how to efficiently use NestJS global

Is it possible to seamlessly include all @Global modules into a TestModule without the need to manually import them like in the main application? Until now, I've had to remember to add each global module to the list of imports for my test: await Tes ...

Updating the checkbox status in Angular when the radio button value is changed

I need help with a feature where all the checkboxes are checked based on the value of a radio button, and vice versa when an unchecked radio button is clicked. I have tried to implement this functionality using the following code but have not been successf ...

What is the best way to implement dotenv in a TypeScript project?

Attempting to load .env environment variables using Typescript. Here are my .env and app.ts files: //.env DB_URL=mongodb://127.0.0.1:27017/test // app.ts import * as dotenv from 'dotenv'; import express from 'express'; import mongoo ...

Using TypeScript to implement Angular Draggable functionality within an ng-template

Sorry if this question has been asked before, but I couldn't find any information. I am trying to create a Bootstrap Modal popup with a form inside and I want it to be draggable. I have tried using a simple button to display an ng-template on click, b ...

Issue encountered while executing jest tests - unable to read runtime.json file

I've written multiple unit tests, and they all seem to pass except for one specific spec file that is causing the following error: Test suite failed to run The configuration file /Users/dfaizulaev/Documents/projectname/config/runtime.json cannot be r ...

Error with TypeScript Compiler in Angular 2

Currently, I am facing an issue while trying to run tsc in my Angular 2 application directory. The error message I receive is: Error TS5023: Unknown compiler option 'moduleResolution'. This issue seems to be hindering the startup process, as ts ...

I am encountering difficulties while attempting to import Typescript files. Upon compiling them into Javascript, I am faced with errors in the web browser, specifically the issue of "exports is not defined"

When I run TodoAppUI.js:15, I get an error saying "Uncaught ReferenceError: exports is not defined" In all my classes, I use the export keyword. For example: export class mysclass { public constructor(){} } Even though I have the proper syntax for impo ...

Transforming an array of JavaScript objects into arrays of key-value pairs based on a specific property with ES6 syntax

Consider an array of objects like this: myArray = [ {name: 'First', parent: 1, delta: 2}, {name: 'Second', parent: 1, delta: 1}, {name: 'Third', parent: 2, delta: 1} ]; The goal is to transform this array into an objec ...