追記 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
はいいぞ。