💅

styled-componentsが何故かanyになる謎を解決する

2022/08/02に公開

2016 年ぐらいからある react のプロジェクトを flow→ts に移植した時に発生したバグの解決法を記事化

概要

import styled from "styled-components"

// any
const StyledDiv = styled.div`
  ...
`

// any
const StyledTextField = styled(TextField)`
  ...
`

なぜか styled 関連が全て any になるのでそれを解決する

結論

npm i hoist-non-react-statics@^3.3.0 @types/hoist-non-react-statics@^3.3.0
# or
yarn add hoist-non-react-statics@^3.3.0 @types/hoist-non-react-statics@^3.3.0

上記を実行すれば解決

原因

@types/styled-components では、 以下のように hoist-non-react-statics の型に依存している

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/styled-components/index.d.ts#L23

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/styled-components/index.d.ts#L135-L146

この hoist-non-react-statics、v2→v3 のときに型関連が大幅に変わっており(参考 issue)

  • v2(v2.5.5) まで
    • hoist-non-react-statics 内にindex.d.tsが存在する
    • @types/styled-components で使用されているhoistNonReactStatics.NonReactStatics存在しない
  • v3 以降
    • hoist-non-react-statics 内に index.d.ts が存在しない
    • 代わりに@types/hoist-non-react-staticsを使用する
    • @types/styled-components は@types/hoist-non-react-statics のhoistNonReactStatics.NonReactStatics が import される前提で書かれている

ts の仕様上、hoist-non-react-statics に型定義が存在すると、@types/hoist-non-react-statics の型定義は使用されない。
つまり、hoist-non-react-statics v2 に限って言えば古い型定義を使用することになる。

hoist-non-react-statics はとにかく色々な react 関連のライブラリ(react-router,mui などメジャーなものも含め)に使用されているため、新旧混ざったライブラリがある状態だと何かの間違いで node_modules 内に hoist-non-react-statics v2 が install されてしまい、今回のようなことが起きる

v2 の install を防ぐため、明示的に v3 を install することで解決する

感想

react/styled-components の闇かと思いきや、node のパッケージマネージャーと ts の闇だったという 😇

Discussion