Is it possible to specify a key on an object while allowing TypeScript to infer the value's type automatically?

Currently, I am working on a challenge where I aim to establish specific keys for an object while allowing TypeScript to infer the types of the values. Here is a simple example:


const fooVals = {
  a: null,
  b: null,
  c: null,
  e: null,
}

type TfooVals = typeof fooVals
type JustKeysOfFooVals = { [key in keyof TfooVals]: any};

// TypeScript correctly deduces the types of foo1Vals but does not flag missing key 'e'
const foo1Vals = {
  a: 'string',
  b: 10,
  c: Promise.resolve('string'), 
//  e: () => { console.log('bar') }
}

// Flags missing key 'e', but sets all types as any
const foo2Vals: JustKeysOfFooVals = {
  a: 'string',
  b: 10,
  c: Promise.resolve('string'), 
  e: () => { console.log('bar') }
}

TSPlayground:

Do you think this approach is achievable?

Answer №1

If you're looking for a more efficient solution, my suggestion would be to implement a versatile helper function that restricts its input to a specific category of JustKeysOfFooVals and simply returns the input without broadening it:

const justKeysOfFooVals = <T extends JustKeysOfFooVals>(t: T)=>t;

To utilize this, follow these steps:

const foo1Vals = justKeysOfFooVals({
  a: 'string',
  b: 10,
  c: Promise.resolve('string') , 
//  e: () => { console.log('bar') }
}); // error! property 'e' is missing

const foo2Vals = justKeysOfFooVals({
  a: 'string',
  b: 10,
  c: Promise.resolve('string') , 
  e: () => { console.log('bar') }
}); // okay
foo2Vals.e(); // okay

This approach will flag any absent keys and maintain accuracy in value types. Best of luck with your implementation!

Link to code


Update: The helper function could potentially eliminate unnecessary property checks. In case you require those (which might not be necessary since a value like {a: "a", b: "b"} aligns with type {a: string}), introducing another generic constraint mimicking exact types might help:

type Exactly<T, U> = T & Record<Exclude<keyof U, keyof T>, never>;
const justKeysOfFooVals = <T extends Exactly<JustKeysOfFooVals, T>>(t: T)=>t;

const foo3Vals = justKeysOfFooVals({
  a: 'string',
  b: 10,
  c: Promise.resolve('string') , 
  e: () => { console.log('bar') },
  f: 1 // error!
}); // number is not assignable to never

Link to code

Wishing you success with your endeavor!

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

The property 'label' is not found in the 'string' type in Typescript

Below is the code snippet I am using: interface State { resourceGroup: QuickPickItem | string; } setEvent(state.resourceGroup?.label).catch(err => console.error(err)); When executing this code, I encountered the following error messa ...

Utilizing Ionic Storage to set default request headers through an HTTP interceptor in an Angular 5 and Ionic 3 application

I'm attempting to assign a token value to all request headers using the new angular 5 HTTP client. Take a look at my code snippet: import {Injectable} from '@angular/core'; import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from ...

Important notice: It is not possible to assign refs to function components. Any attempt to do so will result in failure. If you intended to assign a ref, consider

My console is showing a warning when I use the nextJs Link component. Can someone assist me in resolving this issue and providing an explanation? Here is the message from the console: https://i.stack.imgur.com/jY4FA.png Below is a snippet of my code: im ...

Is it possible for a class method in Typescript to act as a decorator for another method within the same

Can we implement a solution like this? class A { private mySecretNumber = 2; decorate (f: (x :number) => number) { return (x: number) => f(this.mySecretNumber * x); } @(this.decorate) method (x: number) { return x + 1; } } I h ...

Angular Material's compatibility update for Angular 8 version

Currently, I'm in the midst of a project that relies on Angular v 8.2.14, and I'm interested in incorporating Angular Material controls into it. I've made an effort to integrate Angular Material into my project, however, the default version ...

Search for specific item within an array of objects

Working on an Angular project, I am attempting to remove an object from an array. To achieve this, I need to filter the array and then update the storage (specifically, capacitor/storage) with the modified array. Here is my function: deleteArticle(id: str ...

Leverage ngFor to loop through a "highly intricate" data structure

In my project, I have stored data in a JSON file structured as follows: { "name": { "source1": ____, "source2": ____, "source3": ____ }, "xcoord": { "source1": ____, "source2": ____, "source3": _ ...

Using Angular, you can effortlessly inject elements into the editable div from any location on the page

Currently, I am working on developing an HTML interface that allows users to input text and send it as a notification to our mobile application. However, I am encountering challenges with the text and dynamically inserted elements using Angular 5; The te ...

Unable to assign a value to a constant within the class constructor

I'm aware that in TypeScript, readonly properties can only be assigned a value within a class constructor. However, I encountered an error while trying to do so inside the constructor of my class, specifically related to an array method handler. class ...

The error message "Error: Unable to access property '_router' when null in NativeScript"

Currently, I am developing an android application using a combination of NativeScript, AngularJS2, and TypeScript. To guide my development process, I have been following the documentation provided by NativeScript, which can be found at this link. However, ...

Confounding Typescript Type Bindings

I am facing an issue with my Typescript component that uses react-jss and the classes object for styling. The error message I'm getting is: Binding element 'classes' implicitly has an 'any' type., and I'm struggling to find a ...

When using Google login in React and Node.js, the requested scope may not be returned as expected

Looking to get additional scope data from Google API during login on my app. I am utilizing react-google-login to obtain a token in my React application with the following scopes: scope='https://www.googleapis.com/auth/user.birthday.read https://www. ...

Using TypeScript with Angular UI Router for managing nested named views in the application

Hey there! I am new to typescript and have a bit of experience with Angular. Lately, I've been struggling to make a common angular-ui-router setup work with typescript. I have a nested named views structure that just doesn't seem to load correctl ...

Creating an interactive questionnaire

Looking for insights on the following situation: I'm working with a survey structure that consists of questions and answers: questions: Question[]; answer: Answer[]; Where Question is defined as: export class Question { idQuestion: string; ...

Combining generic types in an array into a single union

Seeking to retrieve the union type of generics within an array, but currently only able to access what the generic is extended from rather than the actual implementation. type Params = Record<string, number | string | null | undefined> | undefined; t ...

Is there a way to combine multiple array objects by comparing just one distinct element?

Is there a way to combine these two arrays into one? array1 = [ { image: 'image1', title: 'title1' }, { image: 'image2', title: 'title2' }, { image: 'image3', title: 'title3' }, ]; array2 = ...

The design of Next.js takes the spotlight away from the actual content on the

Recently, I've been working on implementing the Bottom Navigation feature from material-ui into my Next.js application. Unfortunately, I encountered an issue where the navigation bar was overshadowing the content at the bottom of the page. Despite my ...

Error reported: "require" identifier not found in Typescript. Issue identified in IONIC 3 development environment

Error Encountered in Typescript: Cannot Find the Name 'require' Location: C:/Users/me/project/src/pages/home/home.ts // Need to require the Twilio module and create a REST client const client = require('twilio')(accountSid, ...

Is there a way to execute the run function of a different Component in Angular 7 without causing the current

Is there a way to execute the ngOnInit() function from one component inside another component without needing to refresh the existing page? ...

Can you explain the distinction between using get() and valueChanges() in an Angular Firestore query?

Can someone help clarify the distinction between get() and valueChanges() when executing a query in Angular Firestore? Are there specific advantages or disadvantages to consider, such as differences in reads or costs? ...