How to define an object type in Typescript without specifying types for keys in order to access keyof

Is there a way to define the type for object keys without individually defining types for each value?

const sizes: Record<string, CSSObject>= {
  md: {
    padding: [10, 24],
    fontSize: 'medium',
  },
  xs: {
    padding: [6, 12],
    fontSize: 'small',
  },
  sm: {
    padding: [8, 16],
    fontSize: 'small',
  },
  lg: {
    padding: [14, 30],
    fontSize: 'large',
  },
} as const;

// Expecting 'md' | 'xs' | 'sm' | 'lg'
type Sizes = keyof typeof sizes;

// However, it is currently returning a string

Answer №1

It seems like you are trying to extract the keys 'md' | 'xs' | 'sm' | 'lg' from the object's properties and ensure that the values associated with these keys are of type CSSObject.

The challenge lies in maintaining type-checking for values of type CSSObject without losing access to the keys of the object. One way to overcome this is by using a generic helper function that allows for the inference of the key type while specifying the type for the values:

function helper<K extends PropertyKey>(obj: Record<K, CSSObject>): Record<K, CSSObject> {
    return obj;
}

const sizes = helper({
  md: {
    padding: [10, 24],
    fontSize: 'medium',
  },
  // ...
});

type Sizes = keyof typeof sizes;
// 'md' | 'xs' | 'sm' | 'lg'

Playground Link

Answer №2

Just wanted to mention something in addition to the helpful response from @kaya3:

The helper function provided is specifically designed to work with CSSObject. In my case, I needed to apply this helper to various objects with different value types, so I came up with a modified version that allows for any type to be passed in:

function adjustValuesAndDeduceKeys<V>() {
    return function <K extends PropertyKey>(obj: Record<K, V>) {
        return obj;
    }
}

const dimensions = adjustValuesAndDeduceKeys<CSSProperties>()({
  md: {
    padding: [10, 24],
    fontSize: 'medium',
  },
  // ...
});

type Dimensions = keyof typeof dimensions;
// 'md' | 'xs' | 'sm' | 'lg'

The drawback is the need to include that additional () in

adjustValuesAndDeduceKeys<CSSProperties>()({
.

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

How can I add a JavaScript-created element into a Primeng TurboTable component?

I am in the process of replacing a custom-made table with PrimeNG's turbotable. The issue I'm facing is that when I try to insert buttons into the table that call specific JavaScript functions, they end up displaying as [object HTMLInputElement] ...

Convert an object to nested JSON in Angular 5

I am struggling with using Angular 5 HttpClient to send a post request because I am having trouble casting an object to nested JSON. For instance, I have the following class: export class Team { members: Person[]; constructor(members: Person[]) ...

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 ...

What is the best way to extract a property if it may be undefined?

Can anyone help with this TypeScript error I'm encountering during build time? Any suggestions would be appreciated. Error Message: TypeError: Cannot destructure property 'site' of '(intermediate value)' as it is undefined. export ...

Using RXJS with the 'never' subject as the specified generic type

In my current Angular project, I am using RXJS and Typescript. The code snippet below shows what I have implemented: const sub = new Subject<never>(); My understanding is that the above line implies that any subscriber defining the 'next' ...

Just starting out with React and encountering the error: Invalid element type, a string was expected

I seem to be going in circles with the following issue as I try to load the basics of a React app into the browser. An error message stating 'Element type is invalid: expected a string (for built-in components) or a class/function (for composite c ...

Determining data types through type guarding in Typescript

interface A = { name: string; ... }; interface B = { name: string; ... }; interface C = { key: string; ... }; type UnionOfTypes = A | B | C | ...; function hasName(item: UnionOfTypes) { if ("name" in item) { item; // typescript knows ...

TypeScript perplexed Babel with its unfamiliar syntax and could not compile it

Encountered a problem while attempting to compile typescript. It appears that babel was unable to comprehend the "?." syntax on the line node.current?.contains(event.target) export function useOnClickOutside(node: any, handler: any) { const handlerRef = ...

The type 'Element | undefined' cannot be assigned to the type 'ReactElement<any, any> | null'

Important Note about Components and Files: Explanation of types.ts File: export interface IIcon { iconName: string; iconSize: string; iconFill: string; } Clarification regarding index.tsx File: import React, { FC } from 'react'; import { ...

Encountering an issue with the UNION operator in Typescript causes an error

Currently, I am utilizing the OR operator within Typescript to designate that a product could be of type ProductI OR CartResponseInterface.Product This is how it is structured: product: ProductI | CartResponseInterface.Product However, when attempting t ...

I am attempting to create a multi-line tooltip for the mat-icon without displaying " " in the tooltip

I attempted to create a multiline tooltip using the example below. However, the \n is showing up in the tooltip. I am looking to add a line break like we would with an HTML tooltip. Check out the code here. ...

TypeScript fails to acknowledge an exported enum

Currently utilizing TypeScript version 2.5.3 along with Angular 5. I have an enum defined in a separate file as follows: export enum eUserType { Driver = 1, Passenger = 2, User = 3 } To import and use it in another ts file, I do the following: i ...

Using TypeScript, leverage bracket notation to access a property of an object using a variable

I am working with an object that has an interface and I am interested in accessing values dynamically using property keys. const userData: IUser = { username: "test", namespace: "test", password: "test" } Object.keys(userData).forEach(propert ...

Unique Version: Some effective tips for utilizing a fork of type definition such as @types

Currently, I am utilizing Typescript 2.0 along with @types and the experience has been quite positive. Thanks to @types, we can easily leverage type definitions by simply installing the package via npm. Surprisingly, I have not delved into how it actually ...

Using a memory cache in development with NextJS does not seem to be effective

When exporting my pages for my simple static blog site, everything runs smoothly and quickly. However, in development mode, the generation of posts is sluggish and I'm looking to implement caching to speed up the process. I have set up a file called p ...

The Karma tool is throwing a TypeError because it is unable to access the 'length' property of a null value

Despite reviewing numerous inquiries regarding this error, none have provided insight into identifying the root cause of the issue. How can I pinpoint the origin of this error and what steps can I take to resolve it? TypeError: Cannot read property ' ...

JSON TypeScript compliant interface

My problem is quite common, but the solutions found on stackoverflow are not suitable for my specific case. I have a collection of objects that I need to manipulate, save, and load as json files. Here's an example of the interface: type jsonValue = s ...

Troubleshooting an Angular application

Just diving into Angular and following along with the tutorial on https://angular.io/tutorial. However, I seem to be facing an issue in Chrome where the const HEROES is not available in my watch list. It keeps showing as "not available". What could be ca ...

defaultValue cannot be used with createContext

Currently, I am endeavoring to establish a context utilizing the createContext method from the react API: import React, { useState, createContext } from 'react'; export const MovieContext = createContext(); export const MovieProvider = (props) ...

Determine the return type of a related function

My goal is to achieve the following functionality: const columns: ColumnDefinition<Pair>[] = [ { label: 'Pair', value: pair => (all ? pair.code : pair.second.code), format: result => result.toUpperCase() }, { label: 'P ...