Skip to content

Change styled() types so that it works with libraries like Framer Motion聽#1417

Open

Description

@jalooc

Describe the enhancement

When extending custom components, Linaria's types require that component to have the style prop [link] (kudos for setting that requirement in the type system - really helpful and solid 馃挭).

This works with usual custom components, but fails to work with e.g. Framer Motion. I believe this is a result of 2 things:

  1. Linaria requiring the styles prop to be CSSProperties [link] (which is fair),
  2. Framer Motion's style prop to be an extension of CSSProperties allowing for passing motion values to styles [link].

Granted, the problem lies probably more on the FM's extension of styles, but I figured it'd be easier for Linaria to relax the styles type requirement, considering that (if I understand correctly) the only purpose that Linaria requires styles is for is setting the custom properties. So the type could be relaxed to a mere Record<string, unknown> maybe?

Motivation

Framer Motion is a great animation library with an api allowing for fantastic components composition/extension with the api that Linaria (and similar css-in-js libs) provide. Would be great if Linaria's types worked with it seamlessly, just like e.g. Styled Components' types do.

Activity

  1. jalooc commented on Jul 12, 2024

    @jalooc
    Author

    So the type could be relaxed to a mere Record<string, unknown> maybe?

    It actually seems to be working - I used patch-package to apply this patch to @linaria/react@6.2.1:

    diff --git a/node_modules/@linaria/react/types/styled.d.ts b/node_modules/@linaria/react/types/styled.d.ts
    index c790c46..f6fa008 100644
    --- a/node_modules/@linaria/react/types/styled.d.ts
    +++ b/node_modules/@linaria/react/types/styled.d.ts
    @@ -11,9 +11,9 @@ type Has<T, TObj> = [T] extends [TObj] ? T : T & TObj;
     export declare const omit: <T extends Record<string, unknown>, TKeys extends keyof T>(obj: T, keys: TKeys[]) => Omit<T, TKeys>;
     declare function styled(componentWithStyle: () => any): (error: 'The target component should have a className prop') => void;
     declare function styled<TProps extends Has<TMustHave, {
    -    style?: React.CSSProperties;
    +    style?: Record<string, unknown>;
     }>, TMustHave extends {
    -    style?: React.CSSProperties;
    +    style?: Record<string, unknown>;
     }, TConstructor extends Component<TProps>>(componentWithStyle: TConstructor & Component<TProps>): ComponentStyledTagWithInterpolation<TProps, TConstructor>;
     declare function styled<TProps extends Has<TMustHave, {
         className?: string;

    and the problem is gone, while the style prop on Linaria components remains type-safe. I'll keep monitoring for the issue while writing more code / corner cases.

  2. espretto commented on Mar 25, 2025

    @espretto

    Hi,

    I had a similar requirement. React's type declarations suggest extending the parent interface of CSS.Properties. If that doesn't work (as in my case) you can try augmenting react's CSS.Properties directly:

    import * as CSS from "csstype";
    
    declare global {
      namespace React {
        interface CSSProperties extends CSS.Properties<string | number> {
          [index: string]: unknown;
        }
      }
    }

    This has to be included by your tsconfig.json before restarting the TS language server.

  3. espretto commented on Nov 19, 2025

    @espretto

    It seems you found a solution using patch-package @jalooc ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancement: proposal 馃挰Improvement of current behaviour that needs to be discussedneeds: triage 馃彿Issue needs to be checked and prioritized

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions