Share
Embed
Transcript
115 slides
-
最新のWebサイト Web Audio API .PSF .PSF .PSF .PSF .PSF .PSF
.PSF .PSF .PSF .PSF .PSF .PSF .PSF -
最新のWebサイト • WebVR • WebGL • Web Audio API •
Single Page Application • WebRTC (P2P) • PWA • and more, more, more… -
Not only on Website • Smartphone App (React Native) •
Server Side JavaScript (Node.js) -
Why using JavaScript? • ⽂文書配布のためのWebはとっくのとうに終 わってる • ちょっとリッチなWebサイトって時代ももう 終わってる •
JavaScriptは多様な夢を実現する⼿手段として地 位を確⽴立しつつある -
Goal of flow Flow is a static type checker for
JavaScript that we built at Facebook. The overall mission of Flow is to deliver an immersive coding experience for JavaScript developers—a fast edit-refresh cycle—even as the codebase evolves and grows. In engineering terms, we identify two concrete goals that are important to this mission: precision and speed. These goals pervasively drive the design and implementation. https://flow.org/en/docs/lang/#toc-flow-goals -
Goal of flow Flow is a static type checker for
JavaScript that we built at Facebook. The overall mission of Flow is to deliver an immersive coding experience for JavaScript developers—a fast edit-refresh cycle—even as the codebase evolves and grows. In engineering terms, we identify two concrete goals that are important to this mission: precision and speed. These goals pervasively drive the design and implementation. https://flow.org/en/docs/lang/#toc-flow-goals -
Precision / 精度 • JavaScriptのバグは⾒見見逃してはいけない • でもエラーを報告しすぎるツールは • 必要最低限のクリティカルなバグを報告する •
精度をあげることで開発ツールの構築も可能 • 例例. IDEによる型補完 https://flow.org/en/docs/lang/#toc-precision -
Speed / 速度 • 速度は精度と相反する • 速度の低下で開発サイクルを遅らせることは JavaScriptの魅⼒力力を損なうことに他ならない • コードを実⾏行行することなく精度の⾼高くバグを
を⾒見見つけることがベスト https://flow.org/en/docs/lang/#toc-speed -
function add(a, b) { return a + b; } add("1",
2); Normal JavaScript -
function add(a, b) { return a + b; } add("1",
2); Normal JavaScript ⾔言語仕様的には問題ないが… -
with flow annotation • サンプルコード // @flow function add(a: number,
b: number): number { return a + b; } add("1", 2); -
with flow annotation • サンプルコード // @flow function add(a: number,
b: number): number { return a + b; } add("1", 2); flowの解析対象の⽬目印 -
with flow annotation • サンプルコード // @flow function add(a: number,
b: number): number { return a + b; } add("1", 2); 引数の 明示的型宣⾔言 -
with flow annotation • サンプルコード // @flow function add(a: number,
b: number): number { return a + b; } add("1", 2); 関数の返り値の 明示的型宣⾔言 -
with flow annotation • サンプルコード // @flow function add(a: number,
b: number): number { return a + b; } add("1", 2); Is it OK…? -
Work for not only annotation console.log("1" * 1); function printResponse(data)
{ console.log(data.res); } printResponse('string response'); -
Work for not only annotation console.log("1" * 1); // Error!
function printResponse(data) { console.log(data.res); } printResponse('string response'); -
Work for not only annotation console.log("1" * 1); // Error!
function printResponse(data) { console.log(data.res); } printResponse('string response'); // Error! -
サポートする機能 • 関数の引数、返り値、変数の明示的型宣⾔言 • Interface • Generic Type • Comment
Type • and so on :) -
How to use? • flow-binをインストール • flow initしてconfig⽣生成 • 解析対象ファイルに
// @flow • flowコマンド実⾏行行 -
flowのいいところ(2) 捨てやすさ • flowはランタイム、コンパイルに関与しない • 捨てるときはflowコマンドの実⾏行行をやめるだけ • アノテーションを消したければflow-remove- typesを使う •
https://flow.org/en/docs/tools/flow-remove-types/ -
flowが有効でない場⾯面 • ⼩小規模プロジェクトの場合 • 本当に型必要? • 1ファイルが巨⼤大過ぎる場合 • 新規プロジェクトの場合 •
有効だがTypeScriptの使⽤用も視野に -
Sample code function makeMemo(title, text) { const memo = {
title: title, text: text, }; return memo; } -
Start flow // @flow function makeMemo(title, text) { const memo
= { title: title, text: text, }; return memo; } -
Start flow // @flow function makeMemo(title, text) { const memo
= { title: title, text: text, }; return memo; } flow導⼊入の 第⼀一歩 -
Declare type // @flow function makeMemo(title: string, text: ?string): Object
{ const memo = { title: title, text: text, }; return memo; } -
Declare type // @flow function makeMemo(title: string, text: ?string): Object
{ const memo = { title: title, text: text, }; return memo; } 引数の型宣⾔言 -
Declare type // @flow function makeMemo(title: string, text: ?string): Object
{ const memo = { title: title, text: text, }; return memo; } 引数の型宣⾔言 返り値の型宣⾔言 -
Fix // @flow function makeMemo(title: string, text: ?string): Object {
const memo = { title: title, text: `${title}\n${text}`, }; return memo; } textの⼿手前に改⾏行行を挟んで タイトルを挿⼊入 -
修正ポイントを探す // @flow function makeMemo(title: string, text: ?string): Object {
const memo = { title: title, text: `${title}\n${text}`, }; return memo; } Oh, text is nullable! -
Check argument // @flow function makeMemo(title: string, text: ?string): Object
{ let content = text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, }; return memo; } textがnull, undefinedで ないことをチェックする -
Add argument // @flow function makeMemo(title: string, status: string, text:
?string): Object { let content = text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, status: status, }; return memo; } 引数追加 オブジェクトに反映 -
Add argument // @flow function makeMemo(title: string, status: string, text:
?string): Object { let content = text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, status: status, }; return memo; } しかしここに意図しない⽂文字 列列が⼊入っても気がつけない… -
Original type // @flow type Fukuoka = 'mentaiko'; const omiyage:
Fukuoka = 'mentaiko'; const nisemono: Fukuoka = 'takoyaki'; -
Original type // @flow type Fukuoka = 'mentaiko'; const omiyage:
Fukuoka = 'mentaiko'; // Works! const nisemono: Fukuoka = 'takoyaki'; // Error -
ENUM // @flow // Use or statement for type type
MemoStatus = 'public' | 'private' | 'draft'; -
ENUM // @flow // Use or statement for type type
MemoStatus = 'public' | 'private' | 'draft'; どれか1つに当てはまれば MemoStatusとして識別される -
Use ENUM // @flow type MemoStatus = 'public'|'private'|'draft'; function makeMemo(title:
string, status: MemoStatus, text: ?string): Object { let content = text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, status: status, }; return memo; } -
Use ENUM // @flow type MemoStatus = 'public'|'private'|'draft'; function makeMemo(title:
string, status: MemoStatus, text: ?string): Object { let content = text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, status: status, }; return memo; } 期待する値の型を宣⾔言 -
Use ENUM // @flow type MemoStatus = 'public'|'private'|'draft'; function makeMemo(title:
string, status: MemoStatus, text: ?string): Object { let content = text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, status: status, }; return memo; } 期待する値の型を宣⾔言 引数に型宣⾔言 -
コードとにらめっこ // @flow type MemoStatus = 'public'|'private'|'draft'; function makeMemo(title: string,
status: MemoStatus, text: ?string): Object { let content = text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, status: status, }; return memo; } -
コードとにらめっこ // @flow type MemoStatus = 'public'|'private'|'draft'; function makeMemo(title: string,
status: MemoStatus, text: ?string): Object { let content = text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, status: status, }; return memo; } ここの型が曖昧すぎる -
Object type // @flow type Item = { id: number,
name: string, description?: string, } -
Object type // @flow type Item = { id: number,
name: string, description?: string, } const validItem: Item = { id: 32, name: 'item_name', }; // Works validItem.description = 'description'; // Works -
Object type // @flow type Item = { id: number,
name: string, description?: string, } const validItem: Item = { id: 32, name: 'item_name', }; // Works validItem.description = 'description'; // Works validItem.id = '32'; // Error -
Object type // @flow type Item = { id: number,
name: string, description?: string, } const validItem: Item = { id: 32, name: 'item_name', }; // Works validItem.description = 'description'; // Works validItem.id = '32'; // Error 型違反 -
Don’t allow extra key // @flow type Item = {|
id: number, name: string, |} -
Don’t allow extra key // @flow type Item = {|
id: number, name: string, |} 定義していないキーを 許容しない -
Don’t allow extra key // @flow type Item = {|
id: number, name: string, |} const validItem: Item = { id: 32, name: 'item_name', extraProp: 'extra!', }; -
Don’t allow extra key // @flow type Item = {|
id: number, name: string, |} const validItem: Item = { id: 32, name: 'item_name', extraProp: 'extra!', // Error }; 型宣⾔言していないキーが エラーになる -
It’s time to fix! // @flow type MemoStatus = 'public'|'private'|'draft';
function makeMemo(title: string, status: MemoStatus, text: ?string): Object { let content = text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, status: status, }; return memo; } このObject, 型として宣⾔言できそう -
It’s time to fix! // @flow type MemoStatus = 'public'|'private'|'draft';
function makeMemo(title: string, status: MemoStatus, text: ?string): Object { let content = text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, status: status, }; return memo; } // @flow type Memo = {| title: string, text: ?string, status: MemoStatus, |} -
It’s time to fix! // @flow type MemoStatus = 'public'|'private'|'draft';
type Memo = {| title: string, text: ?string, status: MemoStatus, |} function makeMemo(title: string, status: MemoStatus, text: ?string): Memo { let content = text; if (text) { content = `${title}\n${text}`; } const memo: Memo = { title: title, text: content, status: status, }; return memo; } -
Without flow function makeMemo(title, status, text) { let content =
text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, status: status, }; return memo; } -
Without flow function makeMemo(title, status, text) { let content =
text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, status: status, }; return memo; } ҙਤ͠ͳ͍ܕɺ͕ ͞Εͯؾ͚ͮͳ͍ -
Without flow function makeMemo(title, status, text) { let content =
text; if (text) { content = `${title}\n${text}`; } const memo = { title: title, text: content, status: status, }; return memo; } ҙਤ͠ͳ͍ܕɺ͕ ͞Εͯؾ͚ͮͳ͍ 0CKFDUͷߏ͕ มΘͬͯͰ͖ͳ͍ -
With flow // @flow type MemoStatus = 'public'|'private'|'draft'; type Memo
= {| title: string, text: ?string, status: MemoStatus, |} function makeMemo(title: string, status: MemoStatus, text: ?string): Memo { let content = text; if (text) { content = `${title}\n${text}`; } const memo: Memo = { title: title, text: content, status: status, }; return memo; } -
With flow // @flow type MemoStatus = 'public'|'private'|'draft'; type Memo
= {| title: string, text: ?string, status: MemoStatus, |} function makeMemo(title: string, status: MemoStatus, text: ?string): Memo { let content = text; if (text) { content = `${title}\n${text}`; } const memo: Memo = { title: title, text: content, status: status, }; return memo; } ҙਤ͠ͳ͍ܕɺ͕ ͞ΕͨΒqPX͕ڭ͑ͯ͘ΕΔ -
With flow // @flow type MemoStatus = 'public'|'private'|'draft'; type Memo
= {| title: string, text: ?string, status: MemoStatus, |} function makeMemo(title: string, status: MemoStatus, text: ?string): Memo { let content = text; if (text) { content = `${title}\n${text}`; } const memo: Memo = { title: title, text: content, status: status, }; return memo; } ҙਤ͠ͳ͍ܕɺ͕ ͞ΕͨΒqPX͕ڭ͑ͯ͘ΕΔ ಠࣗఆٛͷܕએݴʹΑΓ 0CKFDUͷߏ͕໌֬ʹ -
With flow // @flow type MemoStatus = 'public'|'private'|'draft'; type Memo
= {| title: string, text: ?string, status: MemoStatus, |} function makeMemo(title: string, status: MemoStatus, text: ?string): Memo { let content = text; if (text) { content = `${title}\n${text}`; } const memo: Memo = { title: title, text: content, status: status, }; return memo; } ҙਤ͠ͳ͍ܕɺ͕ ͞ΕͨΒqPX͕ڭ͑ͯ͘ΕΔ ಠࣗఆٛͷܕએݴʹΑΓ 0CKFDUͷߏ͕໌֬ʹ ಠࣗͷܕఆٛͰ ΑΓݎ࿚ͳίʔσΟϯάΛ