Using the css function within styled-components

Struggling with implementing the media templates example from the documentation and figuring out how to type the arguments for the css function in plain JS:

const sizes = {
  desktop: 992
}

const media = Object.keys(sizes).reduce((acc, label) => {

  acc[label] = (...args) => css`    // <----- need help typing args

    @media(max-width: ${sizes[label]}px) {
      ${css(...args)}
    }

  `

  return acc
}, {})

If you are familiar with TypeScript but not styled-components, args is a tagged template literal used as below:

media.desktop`
  background-color: blue;
  ${variable}
`

Attempted typing args as TemplateStringsArray but confronted with complaints from TS regarding spread argument types. Changing the type to TemplateStringsArray[] causes issues with the css() function expecting at least one argument but receiving 0 or more.

Answer №1

When creating a tagged template, the signature should follow this format:

(literals: TemplateStringsArray, ...placeholders: any[]) => string
. In this structure, literals represent the strings in the template and placeholders refer to the variable values being substituted.

If you wish to pass all arguments to the css function, utilizing call is recommended. TypeScript doesn't support direct spreading due to necessary arguments within css that need validation by the compiler:

acc[label] = (...args: any[]) => css`  
  @media(max-width: ${sizes[label]}px) {
    ${css.call(undefined, ...args)}
  }

`

To ensure accurate typing when using the media.* functions, an optimized version would be as follows:

const sizes = {
    desktop: 992
}

const media = Object.keys(sizes).reduce((acc, label) => {

    acc[label] = (literals: TemplateStringsArray, ...placeholders: any[]) => css`      
    @media(max-width: ${sizes[label]}px) {
        ${css(literals, ...placeholders)}
    }

    `;
    return acc
}, {} as Record<keyof typeof sizes, (l: TemplateStringsArray, ...p: any[]) => string>)

Answer №2

The Titian Cernicova-Dragomir approach is impressive, but unfortunately it does not suit my needs as it generates a string with commas. To resolve this issue, I decided to incorporate the join method into the css function.

import { css } from "styled-components";

const sizes = {
  desktop: 730,
};

const media = Object.keys(sizes).reduce(
  (acc, label) => {
    acc[label] = (literals: TemplateStringsArray, ...placeholders: any[]) =>
      css`
        @media (max-width: ${sizes[label]}px) {
          ${css(literals, ...placeholders)};
        }
      `.join("");
    return acc;
  },
  {} as Record<
    keyof typeof sizes,
    (l: TemplateStringsArray, ...p: any[]) => string
  >,
);

export default media;

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 service has terminated unexpectedly because of signal: Ended prematurely: 9

I'm encountering the error 'Service exited due to signal: Killed: 9' and am unable to launch my app. I've come across information suggesting that this may be caused by memory leaks or a lengthy startup time for the app. In all honesty, ...

What are the essential requirements for an Angular application to function properly with minimal dependencies?

If a new developer wants to begin learning Angular from scratch, what are the essential npm packages that they need to install in order to start building an Angular application with minimal dependencies? ...

Blend the power of Node's CommonJS with the versatility of Typescript's ES modules

I currently have a Node.js v10 legacy application that was built using CommonJS modules (require). The entire codebase is written in JavaScript. However, I am considering upgrading the app and refactoring a specific part of it to use TypeScript modules ( ...

Modify a single parameter of an element in a Map

Imagine I have a map data type exampleMap: Map<string, any> The key in the map is always a string, and the corresponding value is an object. This object might look like this: { name: 'sampleName', age: 30} Now, let's say the user se ...

How can we efficiently load paginated data from a database while still implementing pagination using Angular Material?

I have a large table with more than 1000 entries that I want to display using a <mat-table></mat-table>. Since loading all the entries at once would be too much, I am looking to implement pagination and load only 20 entries per page. The chal ...

Tips for saving a variable in Angular that is being received through a subscription as JSON:

Below is an example of the json I have: [{"id":"1","date":"2020-02-21","status":"present","studentid":"1"},{"id":"2","date":"2020-02-24","status":"present","studentid":"1"}] I am struggling to store the date in a variable using Angular when it is being s ...

Pattern Matching for Excluding Multiple Specific Phrases

I need to restrict what a user can enter into a field based on previous entries that are already in the system. For instance, the user has already entered these values into the database: ["typescript", "C#", "python"] If they type one of these existing ...

Tips for inputting transition properties in Material UI Popper

Currently, I am making use of material ui popper and I would like to extract the transition into a separate function as illustrated below: import React from 'react'; import { makeStyles, Theme, createStyles } from '@material-ui/core/styles& ...

What is the best way to show/hide group items in a PrimeNG dropdown menu?

Is it possible to show or hide group items when clicking on the group header if the group contains items? For instance, I would like to display 3 items (AA, BB, CC) in a dropdown menu. The first 2 options (AA and BB) should be selectable, but when I click ...

Dealing with null-safe operators issues has been a challenge for me, especially while working on my Mac using

Hey everyone! I'm encountering errors when using null sage operators in TypeScript. Can someone help me figure out how to solve this issue? By the way, I'm working on Visual Studio Code for Mac. https://i.stack.imgur.com/huCns.png ...

Error occurs when attempting to test both boolean and number data within an ngIf statement

In the scenario where I am working with a template that includes a boolean called readOnly and an array known as arrayOfStuff: <span *ngIf="!readOnly && arrayOfStuff && arrayOfStuff.length">Hey</span> When running eitherng bui ...

When executed, the Node application successfully compiles

I have a TypeScript application that runs smoothly in development mode using ts-node. However, after building the application, I encounter some unexpected warnings and errors. This is my tsconfig.json: { "compilerOptions": { "incremen ...

Testing the throwing of errors when running Karma by utilizing sinon.spy on global functions like parseInt

I'm currently facing an issue with monitoring the usage of parseInt within my function. This is a Proof of Concept for integrating TypeScript into our company's workflow. I've tried following two different tutorials on testing Sinon, but no ...

Tips for obtaining a variable step size in react-chartjs-2

I am currently utilizing Chart.js in typescript to create graphical charts. My objective is to dynamically adjust weight values while maintaining a specified minimum and maximum. Specifically, I aim to display 5 ticks on the Y-axis regardless of the incomi ...

Using Angular 2, NodeJS, and Mongoose to send data from an Angular 2 frontend to a NodeJS backend REST API. However, encountering an issue where the Node API logs show that the OPTIONS

I am facing an issue with sending data from my Angular2 frontend API to the backend client, which is built using NodeJS and mongoose. When I inspect the data being sent on the Angular2 client through console.log, I can see that the correct values are being ...

Manage thrown errors using http.post().subscribe()

There is a backend API for logging in with the possibility of returning a 401 Unauthorized error if the password provided is incorrect. I am wondering how to effectively manage and handle exceptions raised in Angular when interacting with this API. this.h ...

The functionality of `import { Dialogs } from "@nativescript/core"; seems to be malfunctioning

For my project, I am in need of using Dialogs. Unfortunately, the import from @nativescript/core as mentioned in their documentation is not working. I keep encountering this error: Module '"@nativescript/core"' has no exported member &a ...

Stop allowing the transmission of unfamiliar string constants, but still permit the transmission of adaptable strings

Consider the TypeScript code snippet below: const namesList = { john: 25, emma: 30, jacob: 35, } type NameType = keyof typeof namesList function getPersonAge< Name extends string, Result = Name extends NameType ? number ...

The local storage gets wiped clean whenever I am using this.router.navigate

I am in the process of building a website using Angular 5 and Typescript. One important aspect of my implementation is utilizing localStorage to store the JWT Token for user login. Whenever I click on a link (either Home or any other link), I implement a ...

Optimal strategies for managing server-side validation/errors in Angular applications

Back in the day, I used to retrieve HTTP responses with a TypeScript object. validateTokenHttp(token: string): Observable<User> { return this.http.get<User>(`${environment.api}/auth/verifyToken/${token}`); } Sometimes it would return a Us ...