Leveraging the keyof keyword to access a specific property within a type

I have a variety of types that I need to work with. For example:

type Type = {
    prop1: number;
    prop2: string;
    prop3: someOtherType
}
type Props = keyof Type

I am aware that using an "indexed access type" allows me to extract the type of propN, like this: type Num = Type["prop1"]. However, my goal is to incorporate this into a function as follows:

function(p: Props) {
    // ...
    let something = somethingElse as Type[p]
    // Typescript struggles to infer the type
    // ...
}

Ultimately, I would like to be able to call the function like this:

let a = function("prop1");
// a should be of type number

Unfortunately, this approach is not feasible and results in the error message:

'p' refers to a value, but is being used as a type here. Did you mean 'typeof p'?

If I switch to using typeof p, then Type[typeof p] yields the union type number | string | someOtherType.

I have explored options such as generics, but it seems that they may not provide a solution to this issue.

Answer №1

It seems that the goal you are aiming for can be accomplished by employing a universal function like this:

function bar<U extends keyof CustomType>(q: U) {
    let anything = anotherThing as U
}

Answer №2

A more detailed example:

type ValueOf<T> = T[keyof T];

type ObjectType = {
    key1: number;
    key2: string;
    key3: boolean;
}

type Keys = keyof ObjectType;

function bar<T extends Keys>(param: T): ObjectType[T] {
    let value = "";
    return value as ObjectType[T];
}

const x = bar("key1"); // x is number
const y = bar("key2"); // y is string
const z = bar("key3"); // z is boolean

Answer №3

Upon calling typeof p, you can ascertain the Typescript variant of the Javascript variable p. As demonstrated by function(p: Props), you have specified that the type of p is Props, signifying that it could be any of the keys within Props.

If you wish for your code to determine exactly which key p represents, utilizing a generic is imperative. Otherwise, without this specification, the type of p will default to Props due to function(p: Props).

In circumstances where the type of p is generic, employing an indexed access type assertion is recommended.

function myFunc<P extends Props>(p: P) {
    // ...
    let something = somethingElse as Type[P]
    // The type cannot be automatically deduced
    // ...
}

However, if all typings are appropriately defined, there may be no need for an assertive statement with as.

type Type = {
  prop1: number;
  prop2: string;
}
type Props = keyof Type

function myFunc<P extends Props>(p: P) {
  const type: Type = { prop1: 0, prop2: "" };
  return type[p]; // the type is inferred as `Type[P]`
}

const one = myFunc("prop1"); // evaluates to type number
const two = myFunc("prop2"); // yields type string

Check out the Typescript Playground Link here

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

Filter the angular accordion by passing a simple array value into the input

I am looking to filter my array of accordion items based on the value of the question matching the input I provide. I have tried using the filter method for this. this.accordionItems = [ { "topic":"polizze", " ...

Transferring 'properties' to child components and selectively displaying them based on conditions

This is the code for my loginButton, which acts as a wrapper for the Button component in another file. 'use client'; import { useRouter } from 'next/navigation'; import { useTransition } from 'react'; interface LoginButtonPr ...

Are there any comparable features in Angular 8 to Angular 1's $filter('orderBy') function?

Just starting out with Angular and curious about the alternative for $filter('orderBy') that is used in an AngularJS controller. AngularJS example: $scope.itemsSorted = $filter('orderBy')($scope.newFilteredData, 'page_index&apos ...

What is causing the consistent occurrences of receiving false in Angular?

findUser(id:number):boolean{ var bool :boolean =false this.companyService.query().subscribe((result)=>{ for (let i = 0; i < result.json.length; i++) { try { if( id == result.json[i].user.id) ...

Webpack is struggling to locate core-js paths when running on Windows operating systems

When running webpack, I am encountering the following errors: ERROR in ./node_modules/core-js/index.js Module not found: Error: Can't resolve './es' in 'pathtoproject\node_modules\core-js' @ ./node_modules/core-js/index. ...

Leverage generic types and allow acceptance of objects with arbitrary keys

Is it possible to allow the Use function argument type to accept any unknown key, as well as correctly type the keys from SomeGeneric? function Example (opt: { valid?: boolean }) { } type SomeGeneric = Parameters<typeof Example>[0] function Use(op ...

What strategies can be employed to improve generic inference skills?

Looking at the scenario provided below, how can we enhance code reusability in a manner similar to foobarA? interface F<T, U extends string> { t: T, f: (u: U) => void } declare const foo: <T, U extends string>(type: U) => F<T, U>; ...

Tips on implementing computed properties in Vue.js while using TypeScript

There is a significant amount of documentation on how to utilize Vue.js with JavaScript, but very little information on using TypeScript. The question arises: how do you create computed properties in a vue component when working with TypeScript? According ...

The console is displaying a promise that is pending, rather than the desired data

Here is the content of my file: 'use strict' import * as moment from "moment"; import { Report} from "./Report"; import { Timeframe} from "./Timeframe"; import { ReportComparison } from "./ReportComparison"; function test(firstFrom: string, fi ...

Using TypeScript to chain observables in a service and then subscribing to them in the component at the end

Working with Platform - Angualar 2 + TypeScript + angularFire2 Within my user.service.ts file, I have implemented the following code to initiate an initial request to a firebase endpoint in order to fetch some path information. Subsequently, I aim to util ...

Enhancing AWS Amplify Auth elements using TypeScript

My goal is to enhance the existing Auth components within AWS Amplify like SignIn, SignUp, etc. by customizing the showComponent() function to display a personalized form. I found a helpful guide on how to achieve this at: While working on my nextjs proje ...

Retrieve: Type 'string | undefined' does not match the parameter type 'RequestInfo'

When using the fetch function, I encountered an error with the "fetchUrl" argument: Error: Argument of type 'string | undefined' is not assignable to parameter of type 'RequestInfo'. This is the code snippet where the error occurred: ...

How to make a POST request with custom headers in NestJS

Has anyone successfully sent a Post request using Nestjs to a 3rd party API that needs authorization through a client-key and secret? I am looking for guidance on how to include headers in the request, ideally using axio's HttpService. ...

Resolving TypeScript error when importing images statically in Next.js

In order to enhance the performance of images in my nextjs app, I am working on image optimization. However, I encountered an issue stating: Cannot find module '/images/homeBg.jpg' or its corresponding type declarations. The image is actually st ...

Hover shows no response

I'm having trouble with my hover effect. I want an element to only be visible when hovered over, but it's not working as expected. I've considered replacing the i tag with an a, and have also tried using both display: none and display: bloc ...

Tips to store Google fonts in the assets directory

I've included this link in my styles.scss @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap'); While it works locally, the API fails on production or is blocked. How can I host it within my p ...

Having difficulty specifying the class type in Typescript

I am currently working on defining a 'Definition' type in Typescript. In this case, a Definition could be either a class constructor or an object. Here is the code snippet that illustrates my approach: if (this._isConstructor(definition)) { r ...

Interactive website built on Angular 16 offering advanced search and result display functionalities, along with options to edit and update data

Seeking guidance from experienced Angular developers as I am relatively new to the framework. Any tips or advice would be greatly appreciated. Project Overview: Front-end development using Angular, minimal focus on Back-end (C#) for now. https://i.sstati ...

When executing prisma generate, an error of TypeError is thrown stating that the collection is

While using typescript with Prisma, I encountered an issue when trying to run prisma generate, as it kept throwing the following error: TypeError: collection is not iterable. at keyBy (/node_modules/@prisma/client/generator-build/index.js:57685:21) at ...

An issue has occurred where all parameters for the DataService in the D:/appangular/src/app/services/data.service.ts file cannot be resolved: (?, [object Object])

Upon running the command ng build --prod, an error is encountered. Error in data.service.ts: import { BadInput } from './../common/bad-input'; import { AppError } from './../common/app-error'; import { Injectable } from '@angular ...