LoginSignup
21
19

More than 5 years have passed since last update.

Flowの導入と使い方

Last updated at Posted at 2018-01-18

Flow とは

動的型付けのJavaScriptでも静的型付けができるようになる静的チェッカーです。
つまりJavascript でもTypescriptのように型宣言することができるようになります。

Flow インストール

こちらを参照

Flow 有効

ファイルの一番上に

// @flow

を追加する。

Flowのプリミティブ型

意味
any 静的チェック無効。何も書かないとこれ
mixed 何の型でも受け取るが、利用時に型ごとに絞込が必要
* (実存型) 代入のたびに強制的な型推論を行う
number 数値
boolean ブール
string 文字列
'A' | 'B' | 'C' AかBかCのどれか
Object オブジェクト
{ id: number } id を持つオブジェクト
Array<string> 文字列の配列
Set<string> 文字列のSet
string[ ] 文字列の配列
Function 関数
Class<User> Userクラス
React.DOM React Element
SyntheticInputEvent<EventTarget> React.DOMのEvent

その他、膨大な数の型が載ってます。
https://www.saltycrane.com/flow-type-cheat-sheet/latest/

Flow の特殊な型

mixed

全ての型を代入できるが、利用するときはチェックが必要。

let val: mixed;
val = {};
val = 1;
val = 'test';
if (typeof val === 'function') {
  val();
}
val(); // error

* (実存型)

全ての型を代入できる。また、代入時に強制的に型推論される。

let val: *;
val = 1;          // val is number 
val = 'test';     // val is string 
val = {};         // val is Object
val();            // Error occurs because val is Object 
val = 1;          // val is number 
val.doSomething() // Error occurs because val is number

Maybe ( ? ) の使い方

null も undefined も許可しない

let val: number;
val = 0;
val = undefined; // error
val = null; // error

null と undefined を許可する

let val: ?number;
val = 0;
val = undefined; 
val = null; 

プロパティの必須有無

必須プロパティあり

let val: { id: number };
val = { id: 1 };
val = {  }; // error

必須プロパティなし

let val: { id?: number};
val = {id : 1};
val = { };

おまけ

必須プロパティなし。もしあった場合はnumberかnullかundefinedであること。

let val: { id?: ?number };
val = { id: 1 };
val = { };
val = { id: null };
val = { id: undefined };
val = { id: 'string' }; // error 

React + react-redux Component

e.g.

import React from 'react';
import { connect } from 'react-redux';
import type { MapStateToProps } from 'react-redux';
import { Map } from 'immutable';
import type { Map as MapType } from 'immutable';
import { fetchUsers } from 'actions/users';

type Props = {
  users: MapType,
  selected: string,
};

type State = {
  selected: string,
};

export default class UserSelector extends React.Component<Props, State> {
  static defaultProps = {
    users: new Map()
  };
  constructor(props: Props) {
    super(props);
    this.state = { selected: props.selected };
  }
  componentWillMount() {
    this.props.fetchUsers();
  }
  componentWillReceiveProps(nextProps: Props) {
    if (nextProps.selected) {
      this.setState({ selected: nextProps.selected });
    }
  }
  render() {
    this.props.users.valueSeq().map(user => (
      <div>
        {user.get('id') === this.state.selected && <p>{user.get('name')} selected</p>}
        {user.get('id') !== this.state.selected && <p>{user.get('name')}</p>}
      </div>
    ));
  }
};

const mapStateToProps: MapStateToProps<*, *, *> = (state: *) => {
  return {
    users: state.users,
    selected: state.selected,
  };
};

const mapDispatchToProps = (dispatch: Dispatch<*>) => ({
  fetchUsers : () => dispatch(fetchUsers())
})

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(UserSelector);

外部ライブラリの型

e.g. flow-typed でライブラリを検索してインストールする。

(´ω`) < npm run flow-typed search moment

> my-project@1.0.0 flow-typed /src
> flow-typed "search" "moment"

• rebasing flow-typed cache...done.

Found definitions:
╔════════╤═════════════════╤══════════════╗
║ Name   │ Package Version │ Flow Version ║
╟────────┼─────────────────┼──────────────╢
║ moment │ v2.3.x          │ >=v0.34.x    ║
╟────────┼─────────────────┼──────────────╢
║ moment │ v2.x.x          │ >=v0.28.x    ║
╚════════╧═════════════════╧══════════════╝

(´ω`) < npm run flow-typed install moment@v2.3.x  --skip

e.g. package.json から依存ライブラリの型情報をまとめてインストールする。

(´ω`) < npm run flow-typed install --skip

Learn more

Try flow playground
Flow cheatsheet
Flow Type Cheat Sheet

21
19
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
21
19