The TypeScript type definition for reduce is used to aggregate values in

What is the best way to properly declare a type for this scenario?

interface MediaQueryProps {
  [key: string]: number;
}

const size: MediaQueryProps = {
  small: 576,
  medium: 768,
  large: 992,
  extra: 1200
};

export default Object.keys(size).reduce((acc, cur) => {
  acc[cur] = `(min-width: ${size[cur]}px)`;

  return acc;
}, {});

The issue arises with acc[cur] due to

An element implicitly has an 'any' type because an expression of type 'string' cannot be used to index type '{}'. No index signature with a parameter of type 'string' was found on type '{}'

Is there a method to define a type for this situation without resorting to using any?

Answer №1

To make the accumulator value indexable by a string, you can use Record<string, string>. Simply pass this as the type argument to the reduce function.

interface MediaQueryProps {
  [key: string]: number;
}

const size: MediaQueryProps = {
  small: 576,
  medium: 768,
  large: 992,
  extra: 1200
};

export default Object.keys(size).reduce<Record<string, string>>((acc, cur) => {
  acc[cur] = `(min-width: ${size[cur]}px)`;
  return acc;
}, {});

Check out this Playground link for more details

Answer №2

Experience the power of utilizing Template Literal Types alongside as type casting in TypeScript 4.1. Check out the TypeScript Playground Link.

// .ts
interface MediaQueryProps {
  [key: string]: number;
}

const size = {
  small: 576,
  medium: 768,
  large: 992,
  extra: 1200
} as const;

const mediaQueryKeys = Object.keys(size) as Array<keyof typeof size>;

const mediaQueries = mediaQueryKeys.reduce((acc, cur) => {
  acc[cur] = `(min-width: ${size[cur]}px)`;

  return acc;
}, {} as Record<`${keyof typeof size}`, string>);

export default mediaQueries;

// d.ts
declare const mediaQueries: Record<"small" | "medium" | "large" | "extra", string>;
export default mediaQueries;

Answer №3

Here is a way to achieve the same result utilizing Record and keyof:

const mediaQueries = Object.keys(sizes).reduce((accumulator, current) => {
  accumulator[current] = `(min-width: ${sizes[current]}px)`;

  return accumulator;
}, {} as Record<keyof MediaQueryProperties, string>);

Answer №4

I decided to enhance the approved answer that uses only string types by creating a more accurate approach:

type ScreenSizes = {
  small: number;
  medium: number;
  large: number;
  extra: number;
};

const breakpoints: ScreenSizes = {
  small: 576,
  medium: 768,
  large: 992,
  extra: 1200
};

// Define the type of entry after Object.entries() is used
type BreakpointEntry = [keyof ScreenSizes, ScreenSizes[keyof ScreenSizes]];

// Create a generic helper to ensure all property types are either string or undefined
type Stringify<T> = { [key in keyof T]?: string };

// Customize the Object interface for a custom Object.entries():
interface CustomObject extends ObjectConstructor {
  entries<K extends keyof ScreenSizes, T>(
    o: { [s in K]: T } | ArrayLike<T>
  ): [K, T][];
}

// Implement this customized interface:
const obj: CustomObject = Object;

export default obj
  .entries(breakpoints)
  .reduce<Stringify<ScreenSize>>((acc, cur: BreakpointEntry) => {
    const [key, value] = cur;
    acc[key] = `(min-width: ${value}px)`;

    return acc;
  }, {});

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

If placed in the same document, will promises be executed sequentially?

Let's say I have a function in one file that returns a promise: public async a():Promise<string>{ return 'hi' } In another file, I use this function like so: await service.a.then( hi =>console.log(hi)).catch(err=>{throw err}); ...

When trying to style a Material UI component in Mui v5, no matches for overloads were found

In my attempt to enhance the style of a Material UI Component (TextField) shown in the image, I encountered an error that seems to persist no matter what troubleshooting steps I take. Interestingly enough, I never faced such issues when working with styled ...

Retrieve the values of private variables within a defined function

While experimenting with typescript, I have encountered an issue that I can't seem to resolve. My project involves using Angular, so I will present my problem within that context. Here is a snippet of my code: class PersonCtrl{ private $scope: I ...

Why are other elements not appearing on the index.html page when <app-root> is not included?

Just started delving into Angular and following some tutorials. The project was set up using Angular CLI. Created a new component named navbar on top of the default component and wanted to check if the navbar loads in the index.html at startup. The navbar ...

I've been stuck for hours, is there anything I should include?

I'm attempting to access http://localhost:4200/Personnes/view/:2, but I encountered the following error (ERROR TypeError: Cannot read property 'nom' of undefined) "My personnnes.service.component.ts" `export class PersonnesService { baseUr ...

Overriding a generic property in Typescript allows for a more

I'm troubleshooting an issue with my code: class Base<T> {} class Test { prop: Base<any>; createProp<T>() { this.prop = new Base<T>(); } } const test = new Test(); test.createProp<{ a: number }>(); test.pr ...

Calculating numbers with Math.ceil will result in an increase of 1

After using Math.ceil, one value was rounded up to 50 and the other to 80. However, when I added these two values together, the result unexpectedly turned out to be 131. console.log(Math.ceil(e.currentTarget.clientHeight) // 50 console.log(Math.ceil(e.cu ...

Creating a TypeScript class without using the prototype method

Recently delving into TypeScript and encountering a perplexing issue for which I can't seem to locate a satisfactory explanation... Let's suppose I have a function: function test() { function localAccessMethod() { console.log(' ...

Exploring the usage of array map parameters in rxjs 6 when combined with withLatestFrom

Prior to Rxjs 6, we were able to achieve the following: interface TypeA { payload: any; } source$.pipe( withLatestFrom(source2$, (source1: TypeA, source2: TypeB) => ({ payload: source1.payload, source2 }) ), ) In the resultSelector method ...

Style the date using moment

All languages had a question like this except for JavaScript. I am trying to determine, based on the variable "day," whether it represents today, tomorrow, or any other day. ...

Typescript and RxJS: Resolving Incompatibility Issues

In my development setup, I work with two repositories known as web-common and A-frontend. Typically, I use npm link web-common from within A-frontend. Both repositories share various dependencies such as React, Typescript, Google Maps, MobX, etc. Up until ...

Properly write a function in Typescript that returns the initial property of an object

Looking for a solution to adjust the function below to match the property type: const firstProp = (object: Record<string, unknown>) => object[Object.keys(object)[0]]; Any thoughts on how to modify the function so its return type aligns with the ...

Missing "this" after initialization? (typescript/node/express)

I am currently working on creating a basic http application using node-express. One issue I encountered is that when setting up routes, the constructor of the MyRouter class has access to this, but it seems to be lost within the getRoutes() function. cla ...

What is the best way to implement generics for a zip function in TypeScript?

I want to enhance this JS function by including types: function zip(array1, array2) { const length = Math.min(array1.length, array2.length); const result = []; for (let i = 0; i < length; i++) { result.push([array1[i], array2[i]]); } retur ...

Is it possible to modify a single value in a React useState holding an object while assigning a new value to the others?

In my current state, I have the following setup: const [clickColumn, setClickColumn] = useState({ name: 0, tasks: 0, partner: 0, riskFactor: 0, legalForm: 0, foundationYear: 0 }) Consider this scenario where I only want to update ...

Using TypeScript to define task invocation parameters with AWS CDK's CfnMaintenanceWindowTask

Currently, I am utilizing AWS CDK along with the library @aws-cdk/aws-ssm and TypeScript to construct CfnMaintenanceWindowTask. The code example I am working on is derived from AWS CloudFormation documentation, specifically for "Create a Run Command t ...

What is the best way to create a memoized function in React?

I am currently developing an application using react and typescript, and I am facing a challenge in memoizing a function. const formatData = ( data: number[], gradientFill?: CanvasGradient ): Chart.ChartData => ({ labels: ["a", ...

Script execution is disabled on this system preventing the loading of content - ANGULAR V14

Every time I try to run my Angular project or any ng command, I keep encountering the following error message: ng : File C:\Users\achra\AppData\Roaming\npm\ng.ps1 cannot be loaded because running scripts is disabled on this ...

Building Interactive Graphs with Chart.JS in Angular Using Observables

Having some difficulty setting up a Chart with Angular and Chart.JS. I'm struggling to pass my Observable data into the Chart, no matter what I try. error TS2339: Property 'cool_data' does not exist on type 'Observable<Object>&a ...

Can an Angular 2 module export an interface?

While attempting to export an interface in a NgModule-declaration, I encountered an error message in my editor (Visual Studio Code) stating: [ts] 'MyInterface' only refers to a type, but is being used as a value here. Below is the code snippet c ...