Ensure that the properties of the object adhere to a single interface key

I am struggling with typing an object containing multiple functions, each taking a parameter. The issue lies in the type of the parameter: since each function requires a unique type that is not compatible with others, using a union type is not possible. However, I still want to enforce strict typing for the parameter within the object.

My initial thought was to create an interface with keys corresponding to each function and referencing it in the function definition like MyInterface["subOne"]. Unfortunately, I have been unable to find a generic way to achieve this requirement within the object's typing.

This is my current progress:

interface MyInterface {
  subOne: {
      foo: string
  },
  subTwo: {
      bar: string
  },
  subThree: {
      dahoo: string
  }
}

const myObject: Record<"subOne" | "subTwo" | "subThree", (myParam: MyInterface) => void> = {
    subOne: (myParam: MyInterface["subOne"]) => {
        console.log(myParam.foo)
    },
    subTwo: (myParam: MyInterface["subTwo"]) => {
        console.log(myParam.bar)
    },
    subThree: (myParam: MyInterface["subThree"]) => {
        console.log(myParam.dahoo)
    }
}

The challenge lies in the (myParam: MyInterface) part of the object's typing. How can I instruct TypeScript to require that the function parameters must correspond to one of the interface's keys, rather than utilizing the entire interface? Or perhaps there is a more effective approach to achieving this specific requirement that I am overlooking?

Answer №1

To achieve this, you will need to create a specialized type:

type CustomType<T> = {
  [P in keyof T]: (myArg: T[P]) => void
}

const myCustomObject: CustomType<MyInterface> = {
    subOne: (myArg) => {
        console.log(myArg.foo)
    },
    subTwo: (myArg) => {
        console.log(myArg.bar)
    },
    subThree: (myArg) => {
        console.log(myArg.dahoo)
    }
}

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

A method for enabling mat-spinner's entrance animation

I have recently implemented an Angular Material spinner with a disappearing animation that moves downwards before fading away. Is there a way to disable this animation? I have already tried using keyframes without success. <mat-spinner style="margin: ...

Can the CDK be used to reboot both RDS and EC2 instances simultaneously?

After diving into using CDK, I am a newcomer to programming. I have successfully set up a basic environment including an EC2 instance, a VPC with 2 subnets, and an RDS instance. Additionally, I've configured CloudWatch Alarms to monitor the CPU usage ...

The comparison between using Reflect.decorate and manual decorating in TypeScript

Here are two different decorators that I am using: import "reflect-metadata"; const enum MetadataTypes { Type = "design:type", Paramtypes = "design:paramtypes", ReturnType = "design:returntype" } function DecoratorA(target: any, key: string): void ...

Zero's JSON Journey

When I make an HTTP request to a JSON server and store the value in a variable, using console.log() displays all the information from the JSON. However, when I try to use interpolation to display this information in the template, it throws the following er ...

Using React with Typescript: Passing Props and Defining Data Types

As a relatively new TypeScript enthusiast, I find myself facing some challenges. Specifically, I am struggling with errors in my code and uncertain about how to properly pass props and select the correct type. Any guidance on this matter would be greatly a ...

Is it possible to view the list of errors displayed by vscode when opening a JS file exclusively through the terminal?

Is there a default configuration file that vscode uses to display errors and warnings? I want to identify all issues in my JavaScript project. I don't have any jsconfig.json or tsconfig.json files, only using the //@ts-check directive in some files. ...

Suggestions for improving string.replace across various attributes

I have been working on an application with an editable script feature. As I go through the script, I find myself needing to replace placeholders with local data. While this process is functional, it feels quite messy. initScript(script: LegalScript, lead: ...

How can arrays be formatted to correspond with the type/interface of an external component?

Currently, I am utilizing a treeview library in React that requires an array of NodeModule[] as input. The array I am passing to the tree component is being used in another component with different key names. To align the data structure with NodeModule[], ...

Extending Interfaces in Typescript: Combining Interfaces with Similar Fields

I have encountered an issue where I am attempting to extend two different typescript interfaces, both of which include a classes field that is not compatible. It seems that Interface 'Props' cannot extend both types '{ classes: Record; in ...

Unable to see PrimennGTreeTable icon

While utilizing the PrimeNG TreeTable component, I am facing an issue where the expand/collapse icon is not visible in my code. You can check out the documentation at https://www.primefaces.org/primeng/#/treetable I suspect that the problem lies with the ...

Combining Multiple TypeScript Declaration Files into an NPM Package for Seamless Importing with index.d.ts

I have a unique package structure that includes: myPackage/ |- types/ | |- type1.d.ts | |- type2.d.ts |- src/ | |- someUtilities.ts |- index.ts |- package.json |- tsconfig.json In my package, the index.ts file is handling imports and exports for all th ...

Electron does not have the capability to utilize Google's Speech to Text engine

I am trying to connect my microphone with the Google Speech to Text engine. I came across this page and copied the code into my renderer.ts file, uncommented the lines with const, but when I run it, I encounter an error at line 7 (const client = new speech ...

The input value "HH:MM" does not match the expected format of 'FormatOptions' for this parameter

I created a function that takes in two parameters: data and format. I am attempting to define an ENUM(FormatOptions) for the "format" parameter. However, I encountered the following error: Argument of type '"HH:MM"' is not compatible with param ...

Unable to associate with 'paint' as it is not a recognized attribute of 'mgl-layer' while using mapbox in Angular 9

I am currently working on an Angular 9 project with the latest version of mapbox integrated. My goal is to toggle between displaying contours and museums on the map. To achieve this, I have installed the package: "@types/mapbox-gl": "^1.12. ...

The element is inferred to have an 'any' type due to the inability to use a 'string' type expression to index the 'Palette' type

Encountering an issue: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Palette'. No index signature with a parameter of type 'string' was found on type &ap ...

What is the best way to modify the KeyName in an object?

Having difficulty parsing an Object by changing keynames due to the error message "Element implicitly has an 'any' type because expression of type 'keyof SignInStore' can't be used to index type '{}'". interface SignInSto ...

Error in TypeScript when using Google Maps React with Next.js: there is a possibility that infoWindow.close is undefined

Working on a small project in next.js (typescript) utilizing the google maps api with a KmlLayer. I want my map to interact with another component, SensorInfo. The current setup allows for smooth interaction between them - when SensorInfo is closed, the in ...

Retrieve the template parameter from a generic type

While I have experience extracting string from string[], this particular scenario is proving to be quite challenging: type example<T = boolean> = true; // with just "example", how can I retrieve the template parameter "boolean" in this case? type T ...

I encountered an issue with TypeScript when attempting to post a message back to the source

Here is a snippet of my code window.addEventListener('message', (e) => { e.source.postMessage('hi there, I hear you!', '*'); }); Encountered an error: [ts] The type '((message: any, targetOrigin: string, transfer? ...

What is the best way to ensure TypeScript recognizes a variable as a specific type throughout the code?

Due to compatibility issues with Internet Explorer, I find myself needing to create a custom Error that must be validated using the constructor. customError instanceof CustomError; // false customError.constructor === CustomError; // true But how can I m ...