Slide 1

Slide 1 text

Optional Chaining について

Slide 2

Slide 2 text

自己紹介 Masatoshi Morita フロントエンドエンジニア 普段はReact / Vue / Node.js あたりを書いています twitter: @texdeath

Slide 3

Slide 3 text

Agenda Optional Chaining とは~基本的な使い方 コード上の利点、コンパイル後 まとめ

Slide 4

Slide 4 text

Optional Chaining Object のプロパティ値参照で、プロパティの存在チェックを明示的に書かなくても処理し てくれる仕組み TC39 Proposals では現在Stage 3(Candidate) TypeScript ではversion3.7 で先行的に導入(11 月リリース) 10/1 にbeta がリリースされており、playground でも試せる

Slide 5

Slide 5 text

基本的な使い方 存在しない可能性があるようなチェーンされたプロパティにアクセスする API の返却結果など、どのプロパティがRequired であるかについて保証がないようなオブ ジェクトの内容を操作する

Slide 6

Slide 6 text

定義ケース comment.author.name を定義したい type Comment = { type Comment = { message: string message: string author?: { author?: { name: string name: string detail?: string detail?: string } } }; }; declare const comment: Comment; declare const comment: Comment;

Slide 7

Slide 7 text

定義ケース name はプロパティとして存在していないかもしれないので、当然コンパイルエラーにな る // Object is possibly 'undefined'. // Object is possibly 'undefined'. const name = comment.author.name; const name = comment.author.name;

Slide 8

Slide 8 text

アクセス方法・返り値 ? 演算子を使用して中間のプロパティにアクセスできる 返り値がなければ、undefined を返す 当然手前のプロパティが存在しない場合(chain が足りない)場合はコンパイルエラーに なる const name = comment?.author?.name; const name = comment?.author?.name; // string | undefined // string | undefined console.log(name); console.log(name); const comment = { const comment = { message: "hoge" message: "hoge" }; };

Slide 9

Slide 9 text

関数呼び出しに対して使用する 関数呼び出しにも使用できる async function makeRequest(url: string, log?: (msg: string) => void) { async function makeRequest(url: string, log?: (msg: string) => void) { // log 関数が引数に渡されていれば実行する // log 関数が引数に渡されていれば実行する log?.(`Request started at ${new Date().toISOString()}`); log?.(`Request started at ${new Date().toISOString()}`); const result = (await fetch(url)).json(); const result = (await fetch(url)).json(); log?.(`Request finished at at ${new Date().toISOString()}`); log?.(`Request finished at at ${new Date().toISOString()}`); return result; return result; } }

Slide 10

Slide 10 text

コード上の利点 存在していないかもしれないプロパティにアクセスする際のガード節を除去できる null やundefined のチェックを書く必要がなく、より簡潔なコードを記述できる const name = (comment.author === null || comment.author === undefined) ? const name = (comment.author === null || comment.author === undefined) ? undefined : comment.author.name; undefined : comment.author.name; // ↓ // ↓ const name = comment?.author?.name; const name = comment?.author?.name;

Slide 11

Slide 11 text

Optional Chaining の論理演算子 comment.author.name の返り値が空文字だったとき、これらは同じ出力結果になる let name: string = "hoge"; let name: string = "hoge"; // ----- Logical operator ----- // ----- Logical operator ----- if (comment && comment.author && comment.author.name) { if (comment && comment.author && comment.author.name) { name = comment.author.name; name = comment.author.name; } } console.log(`name: ${name}`) console.log(`name: ${name}`) // ----- Optional chaining ----- // ----- Optional chaining ----- if (comment?.author?.name) { if (comment?.author?.name) { name = comment.author.name; name = comment.author.name; } } console.log(`name: ${name}`) console.log(`name: ${name}`)

Slide 12

Slide 12 text

Optional Chaining の論理演算子 厳密には論理AND はNaN や0 、false などのfalsy な値に特別に作用するので、Optional Chaining でコンパイル後は出力結果が異なる Optional Chaining はコンパイル後、OR 演算子とvoid 演算子を使って評価している // ----- Logical operator( コンパイル後) ----- // ----- Logical operator( コンパイル後) ----- if (comment && comment.author && comment.author.name) { if (comment && comment.author && comment.author.name) { name = comment.author.name; name = comment.author.name; } } // ----- Optional chaining( コンパイル後) ----- // ----- Optional chaining( コンパイル後) ----- if ((_b = (_a = comment) === null || _a === void 0 ? void 0 : _a.author) === null || _b === if ((_b = (_a = comment) === null || _a === void 0 ? void 0 : _a.author) === null || _b === name = comment.author.name; name = comment.author.name; } }

Slide 13

Slide 13 text

所感 コード量が減って物理的に見通しが良くなるので、より直感的に書けそう ただ、既存の明示的なガード節がなくなるのはちょっと怖い・・・ 使うのであれば 同じくTypeScript3.7 で導入されるNullish Coalescing と組み合わせて、null のときはデ フォルト値にフォールバックするようにしたほうがよさそう strictNullChecks は常時ON にしたほうがよさそう TypeScript 初心者なので、知見の強い人に意見を聞いてみたい

Slide 14

Slide 14 text

まとめ Optional Chaining を使えば楽にオプショナルなプロパティにアクセスできる コードも読みやすくなる でもコンパイルの時にすり抜けたりしたら怖いので、null チェック自体は厳密にしたほう が良い(と思う)

Slide 15

Slide 15 text

EOF