0

Based on https://tobbelindstrom.com/blog/how-to-create-a-breakpoint-mixin-with-styled-components/ I'm trying to do the same thing in TypeScript but I'm failing to type this function.

import { css } from 'styled-components';
import { breakpoints } from './_variables';

export const respondTo = Object.keys(breakpoints).reduce(
  (accumulator, label) => {
    accumulator[label] = (...args) => css`
      @media (min-width: ${breakpoints[label]}) {
        ${css(...args)};
      }
    `;
    return accumulator;
  },
  {}
);

I tried something like this:

export const respondTo = Object.keys(breakpoints).reduce<Record<string, Function>>(
  (accumulator, label) => {
    accumulator[label] = (...args: Array<String>) => css`
      @media (min-width: ${breakpoints[label]}) {
        ${css(...args)};
      }
    `;
    return accumulator;
  },
  {}
);

but it keeps throwing errors. Right now, it gives me

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.   No index signature with a parameter of type 'string' was found on type '{}'.  TS7053

at breakpoints[label].

AdamKniec
  • 1,607
  • 9
  • 25

1 Answers1

3

This is working

import { css } from "styled-components";

const breakpoints = {
  xs: "480px",
  sm: "768px",
  md: "992px",
  lg: "1200px"
};

type cssParams = Parameters<typeof css>;
const keys = Object.keys(breakpoints) as Array<keyof typeof breakpoints>;

export const respondTo = keys.reduce((accumulator, label) => {
  accumulator[label] = (...args: cssParams) => {
    return css`
      @media (min-width: ${breakpoints[label]}) {
        ${css(...args)};
      }
    `;
  };
  return accumulator;
}, {} as Record<keyof typeof breakpoints, Function>);

The problem was breakpoints[label]: Object.keys() returns type string[], so label becomes string, which is not a valid key of breakpoints.

Alternatively you could re-type your breakpoints to something like Record<string, string>.

I also added cssParams, which would get you after solving this issue ;)

Josef Wittmann
  • 1,259
  • 9
  • 16