LoginSignup
17
9

More than 3 years have passed since last update.

ReactでcreateContextするときにTypeScriptのリントがエラーを吐く場合の対処法

Last updated at Posted at 2019-04-29

追記 2019/12/27:
今現在は、以下の回避案2を使用すると、Definition for rule '@typescript-eslint/no-object-literal-type-assertion' was not foundになります。

どうやら@typescript-eslintがv2で破壊的変更が入ったようです。

Merged both no-angle-bracket-type-assertion and no-object-literal-type-assertion into one rule - consistent-type-assertions.

そういうことで、回避案2は@typescript-eslint/consistent-type-assertionsを使うよう読み替えてください。

'@typescript-eslint/consistent-type-assertions': [
      'error',
      { assertionStyle: 'as', objectLiteralTypeAssertions: 'allow-as-parameter' },
    ],

============= 追記終わり =============

ReactでContext APIを使いたい場合、createContext()をする必要があります。

しかし、'@typescript-eslint''TSLint'のrecommendedをデフォルトのリントルールとして使用している場合では、ここの型定義で少し詰まります。というか自分が詰まりました。TS力の弱さを認識する今日この頃です。

具体的には、「Type assertion on object literals is forbidden, use a type annotation instead.」として怒られます。

interface ContextProps {
  value: string;
  fn: (string) => void;
}

const TabContext = React.createContext({} as ContextProps);
// ここの `{} as ContextProps` が 'Type assertion on object literals is forbidden, use a type annotation instead.' として怒られる。

回避案1:Partialを使用する

Partial<T>を利用することで、<T>のプロパティをすべてオプショナル(つまりvalue?: string;みたいなこと)にすることができる。

そのため、初期値が入力されていなくても問題なく通る。

interface ContextProps {
  value: string;
  fn: (string) => void;
}

const Context = React.createContext<Partial<ContextProps>>();

当初はこの方針で進めていたのだが、すぐに問題に直面した。

ContextPropsのすべてはオプショナルなため、値にundefinedが許容されているとTSは理解するため、ContextのConsumer側ではそのハンドリングをする必要が出てくる。

const { fn } = useContext(Context);
fn && fn('someThing');
// `fn`が存在していることを担保してからしか、`select`を実行できない

正直これは面倒くさいので、回避案2を採用する。

回避案2:'no-object-literal-type-assertion' のオプションを使用して回避する

まず回避する案1としては、'no-object-literal-type-assertion'ルール自体をオフにするがありますが、なるべく完全にオフにするのは避けたいものです。と思い探したところ、オプションが用意されていました。至れり尽くせり。

注意点として、'@typescript-eslint''TSLint'では、オプション名が違ったりするので気を付けてください。'@typescript-eslint'使ってるのに'TSLint'の書き方で修正しようとして、反映されず悩んだ過去があります。;(

// For @typescript-eslint
'@typescript-eslint/no-object-literal-type-assertion': ['error', { allowAsParameter: true}],
// 特に、'error' のとこ、true とか書くと、後ろのオプションが認識されないので注意

// For TSLint
'no-object-literal-type-assertion': [true, { 'allow-arguments': true }],

これで晴れて、React の Context API を TypeScript と一緒に気持ちよく使うことができます。余談ですが、useContextはいいぞ。

参考

17
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
9