メディアクエリを生成するためのより良い型付き関数


8

私はこの投稿をフォローしていますhttps : //medium.com/@samuelresua/easy-media-queries-in-styled-components-690b78f50053

Typescriptで次のコードを作成しましたが、必要any以上に入力を行わなければなりませんでした。

const breakpoints: ObjectMap<number> = {
  small: 767,
  medium: 992,
  large: 1200,
  extraLarge: 1240
};

export const media = Object.keys(breakpoints).reduce((acc: { [key: string]: (...args: any) => any }, label) => {
  acc[label] = (...args) => css`
     @media (min-width: ${breakpoints[label]}px) {
        ${css(...args as [any])};
     }
  `;
  return acc;
}, {});

その結果、メディアクエリブロックでスタイルを記述しているとき、IDEで何の助けもありません。

styled.button<Props>`
  background: red; /* this must be a valid style */
  ${({ theme }) => theme.media.large`
      background: blue;
      foo: bar; /* this isn't caught */
   `

私のmedia機能をどのように改善できるか誰でも知っていますか?

回答:


0

styled-componentsテンプレートの文字列だけでなく、CSSプロパティのオブジェクトも使用できます。オブジェクトは、TypeScriptコンパイラによってよりよく理解されます。これを試して:

const breakpoints: ObjectMap<number> = {
  small: 767,
  medium: 992,
  large: 1200,
  extraLarge: 1240
};

export const media = (size: keyof typeof breakpoints, properties: CSSObject) => ({[`@media (min-width: ${breakpoints[size]})`]: properties});

const MyButton = styled.button<Props>(({ theme }) => ({
  background: red, // this must be a valid style
  ...theme.media('large', {
    background: blue // this is also validated :)
  })
}));

5

これはTypeScriptの問題ではなく、IntelliSenseプラグインの問題だと思います。

TypeScriptの観点からは、バックティック間のコンテンツはtype TemplateStringsArrayです。TypeScriptは文字列の配列を認識するため、有効なCSSプロパティを認識しません。

検証はtypescript-styled-pluginによってプラグインレベルで行われると思います

https://github.com/styled-components/vscode-styled-components/pull/41を参照してください

ここで機能のリクエストまたはバグレポートを送信します


メディアクエリを可能な限り改善したいのですが...入力ありがとうございます。
ミスターエピック

私の仮定が間違っているかどうか、他の人に解決策があるかどうかを見てみましょう。それまでの間、CSS検証が@media CSS at-rules内のスタイルに対して機能していないように見え、IntelliSenseプラグインのこの制限を潜在的に確認しています。
sunknudsen

1
バグレポートを提出しました。github.com/microsoft/typescript-styled-plugin/issues/113
sunknudsen

1

私が正しく理解していれば、あなたはを取り除きたいのですany

方法は次のとおりです。

import {
  css,
  CSSObject,
  SimpleInterpolation,
  FlattenSimpleInterpolation,
} from 'styled-components';

type ObjectMap<T> = {[key: string]: T};

const breakpoints: ObjectMap<number> = {
  small: 767,
  medium: 992,
  large: 1200,
  extraLarge: 1240,
};

export const media = Object.keys(breakpoints).reduce(
  (
    acc: {
      [key: string]: (
        first: TemplateStringsArray | CSSObject,
        ...interpolations: SimpleInterpolation[]
      ) => FlattenSimpleInterpolation;
      // ^^^ this is the first implementation of  `BaseThemedCssFunction`
    },
    label
  ) => {
    acc[label] = (...args) => css`
      @media (min-width: ${breakpoints[label]}px) {
        ${css(...args)};
      }
    `;
    return acc;
  },
  {}
);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.