TypeScript(静的型付け、型推論、Null 安全性)
TypeScriptの利点
静的型付け、型推論、Null 安全性という最近のプログラミング言語のトレ ンドを押さえつつ、それ以外の部分はまんま JavaScript と文法が同じなので使いやすい。
TypeScript のプリミティブ型
・ number ・ string ・ boolean ・ symbol ・ null ・ undefined
型推論
明示的にnumber型を指定したい時は以下のように書く。 ちなみにstrictNullChecks オプションを有効にしないとnullを代入できる
>let n:number=3; > typeof s 'string' >n=null; null
コードで指定しなくともtsの機能によって、システム側で可能性の高い型を自動的に当ててくれる。
>let s='foo'; 'foo' > typeof s 'string'
Null安全性
tsconfig.jsonのstrictNullChecks オプション(もしくはstrictNullChecks)が有効になっていると、nullを代入しようとするとエラーになる。
strictNullChecks が有効になってる場合でも、あえてその変数の 値に Null を許容したい場合、以下のように共用体型を使う。
>let i:number | null=1; //numberかnullを入れることができる。 1 >i=null; null
また、Null以外を入れることもできる。
> let some: number | string | undefined = 'bar'; //numberかstringかundefinedを入れることができる。 >some=50; 50 > some = undefined; undefined
このような自由に定義した型を ストリングリテラル型と言い、enum のように定義できる。
> let pet: 'cat' | 'dog' | 'rabbit' = 'dog'; > pet 'dog' > pet = 'cat'; 'cat' > pet = 'hamster'; [eval].ts(4,1): error TS2322: Type '"hamster"' is not assignable to type '"cat" | "dog" | "rabbit"'
関数型プログラミング
Reactで関数型プログラミングの知識も必要そうなので、こちらもざっと学習した内容をメモ。
高階関数
引数に関数をとったり、戻り値として関数を返したりする関数のこと。 下記だと(4 + 1) × 2 = 10 が実行される。 英語では Higher Order Function というが、ReactのHOC(Higher Order Component)と原理は同じなので、理解しておくと楽らしい。
const hof = (ex, fn) => { return n => fn(n + ex); }; const plusOneDouble = hof(1, n => n * 2); console.log(plusOneDouble(4)); // 10
クロージャ(関数閉包)
以下はクラスで実行ごとに1加算されるカウンター。 クラスを呼び出すごとに、その値を加算していく。 これを関数で普通に作ろうとするとグローバル変数を定義する等の方法を用いざるを得ず、なかなか難しい。
class Counter { constructor(initialCount) { this.c = initialCount; } increment() { return this.c++; } } const counter = new Counter(1); console.log(counter.increment(), counter.increment(), counter.increment()); // 1 2 3
そこで以下のようにクロージャを使う。 こうすることによって変数 c の値が実行ごとにクリアされることなく加算される
const counterMaker = (initialCount) => { let c = initialCount; const increment = () => c++; return increment; }; const count = counterMaker(1); console.log(count(),count(),count()); //123
ジェネレータ
その他にもJavaScriptでは値を保持しつつ繰り返し処理や逐次処理を行うための手段としてジェネレータ関数がある。
戻り値のオブジェクトから next()という関数かを実行できる。 それによ って yield で返された値がその戻り値オブジェクトの value プロパティに格納される。 そしてそれ以 上ジェネレータの中で yield 文が実行されることがなくなると、value プロパティは undefined になり、 done プロパティが true になる。
function* rangeGenerator(end, start = 0) { letn=0; for(leti=start;i<end;i++){ n+=1; yield i; } } const gen = rangeGenerator(3); console.log(gen.next()); // { value: 0, done: false } console.log(gen.next()); // { value: 1, done: false } console.log(gen.next()); // { value: 2, done: false } console.log(gen.next()); // { value: undefined, done: true }
カリー化
端的にいうと複数の引数をとる関数を、ひとつだけ引数をとる関数に分割してネストさせること。 下記のように高階関数を使い、ひとつずつの値を返す関数がネストした高階関数にすることかをカリー化と言う。 2つ目と3つ目の書き方になるが、よりシンプルな3つ目の書き方が望ましい。
constmulti=(n,m)=>n*m; console.log(multi(2, 4)); //8 const curriedMulti = n => { returnm=>n*m; } console.log(curriedMulti(2)(4)); // 8 カリー化 const simpleCurriedMulti = n => m => n * m; console.log(simpleCurriedMulti(2)(4)); //8 カリー化のよりシンプルな書き方
カリー化関数の部分適用
以下の場合、triple は カリー化された高階関数multi のひとつめの引数に3を渡した関数。 こうするとどんな数を渡しても、常に3倍される関数が作れるので便利。
このようにカリー化された関数の一部の引数を固定して新しい関数を作ることを関数の 部分適用と言う。 無駄をなくし、再利用性を高め可読性を上げる。
constmulti=n=>m=>n*m; console.log(multi(3)(5)); // 15 const triple = multi(3); console.log(triple(5)); // 15 カリー化の部分適用
ES6文法 プロミス構文
非同期処理とPromise構文
JavaScript では時間のかかる処理は、ほぼ非同期なのが前提。(通信とかローカルファイルの読み込みとかの外部アクセス処理)
以下のものは起きた、の遅延によりおやすみ、おはよう、起きたの順番で表示されてしまう。
const wakeUp = ms => { setTimeout(()=>{ console.log('起きた');},ms); }; const greet = () => { console.log('お や す み '); wakeUp(2000); console.log('お は よ う ! '); } } greet();
非同期処理ではなく、同期的に処理を行いたい場合は以下のようにPromiseを使う
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); const greet = () => { console.log('お や す み '); sleep(2000) .then(() => { console.log('起 き た '); console.log('お は よ う ! '); }) .catch(err => { console.error('睡眠例外です:',err); }) } greet();
本を読み始めたのでES6 JavaScript再学習まとめメモ
アロー関数
const fn = (a, b) => { return a + b; }; // 単一式の場合はブラケットやreturnを省略できる const fn = (a, b) => a + b; // ブラケットやreturnを省略してオブジェクトを返したい場合は`()`で囲む const fn = (a, b) => ({ sum: a + b });
分割代入
const [n, m] = [1, 4]; console.log(n, m); // 1 4 const obj = { name: 'Kanae', age: 24 }; const { name, age } = obj; console.log(name, age); // Kanae 24
スプレッド構文
『...』をスプレッド演算子と呼ぶ
const arr1 = ['A', 'B', 'C']; const arr2 = [...arr1, 'D', 'E']; console.log(arr2); // [ 'A', 'B', 'C', 'D', 'E', 'F' ] constobj1={a:1,b:2,c:3}; const obj2 = { ...obj1, d: 4, e: 5 }; console.log(obj2); // { a: 1, b: 2, c: 3, d: 4, e: 5 } ##プロパティ名のショートハンド
const foo = 65536; const obj = { foo, bar: 4096 }; console.log(obj); // { foo: 65536, bar: 4096 }
TypeScriptの学習とReact
前々から周りのエンジニア仲間の中でTypeScriptが流行っていて、前々から興味があったのと静的型付け言語を使えるようになりたかったので、学習してみます。 また、業務でReactから少し離れてしまっていたので、こちらも再学習。
とりあえず学習環境を立ち上げるために私物のMacにインストール。
node.jsバージョン管理のためにndenvを入れたいが、 rbenvもついでに共通管理したいのでanyenvを入れて、それ経由でndenvを入れる。
git clone https://github.com/riywo/anyenv ~/.anyenv
echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bash_profile echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
ANYENV_DEFINITION_ROOT(/Users/riywo/.config/anyenv/anyenv-install) doesn't exist. You can initialize it by:
anyenv install --init
でanybenvインストール完了 updateできるように以下をanyenv-updateも入れる
$ mkdir -p $(anyenv root)/plugins $ git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
ndenv入れようとしたけど、nodenv推奨らしいので
anyenv install nodenv
node.jsインストール
最初12.0.0入れたけど、このバージョンは問題があるらしく、あとでyarnが実行できないことが発覚したので、最終的に以下のバージョンをインストール。
nodenv install 12.1.0
reactでとりあえずhello-worldを作るために以下のコマンド
npx create-react-app hello-world --typescript
作成されたディレクトリに入って
yarn start
でクロームが立ち上がりlocalhost:3000で無事にreactが実行されました。
これでReactの環境構築完了です!
Railsチュートリアル3章
Railsチュートリアルで覚えが悪かったところや、分かりにくかったところの更なる理解を目的としてブログを書いていこうと思います。 僕のように今RubyやRails勉強中という初学者の方も多いと思うので、多少はそういう方の参考になればいいなと。 基本的には全体の要約というよりは、自分の気になること、理解に時間の掛かった部分をざっくりまとめる形式にしていこうと思います。 その方が僕の力になると思うからです。
Railsチュートリアルはいきなりやると難しいとの話だったので、ProgateのRuby/Railsコース完了済みです
環境構築を除き、これまではprogateで学習済みの内容だったんですが、ここにきて初めての内容。 Rails初テスト。Rilsチュートリアルはテスト駆動開発(TDD)と言う手法で記述されています。 node.jsのExpressにて単体テスト/統合テストはやったことがあるが、Railsにおいては初めてなので、多少進みが遅くなる
コントローラーテストの基本文
例
test "テスト名" do get static_pages_help_url //GETリクエストをhomeアクションに対して発行 assert_response :success //バグがなければリクエストに対するレスポンスはsucsessになる end
となる。
<!DOCTYPE html> <html> <head> <title>Greeting</title> </head> <body> <p>Hello, world!</p> </body> </html>
htmlの基本構造はだいたいこうなのですが、例えば上記のhtmlのtitleにきちんと望む内容が含まれているかどうかのテストは
assert_selectメソッドを使い
test "テスト名" do get static_pages_home_url assert_response :success assert_select "title", "含まれているかテストしたいhtmlの内容"
assert_selectメソッドでは、特定のHTMLタグが存在するかどうかをテストします 。
次にリファクタリングについて。
テスト駆動開発においてはRED→GREEN→リファクタリング、
つまり、まず一番最初にテストを記述して、そのテストが失敗するコード、成功するコード、より保守のしやすいきれいなコードに書き直すという順に作っていくのですが、そのコードを書き直すという部分。
重複する部分をapplication.html.erbの<%= yield%>にまとめてしまう。
テストを先に書いておくと、リファクタリングをするときもバグを未然に防げて安心できる。
最後に テスト時、成功/失敗の色表示で見やすくしてくれる「minitest reporters 」と、ファイルの変更を検出して必要なテストだけを自動実行してくれる「Guard」を追加。
「minitest reporters 」はtest/test_helper.rbに追加記述するだけ。
「Guard」は初期化コマンドを実行し、
bundle exec guard init
cloud9環境なのでtmuxをインストール sudo yum install -y tmux
Guardは他のターミナルに
bundle exec guard
と打つことでテスト環境を走らせ、ファイルを変更するとリアルタイムにテストしてくれるすごいやつです。 Return(Enter)キーを打つとフルでテストしてくれ、Ctrl+Dで終了。
以上で3章は終了です。
成果物の作成2作品目⑩ 全体の微調整と、readmeファイルの追加、そして完成。
ついに今回で完成です!
今回は全体のコーディングを整えたり、文章を読みやすくしたり誤字脱字を修正したり。
一週間ちょいぐらいしか掛かってないはずなのに、自分で考えるたり、問題を解決したりする時間が多かったせいか、凄く長く感じた気がします。
ざっとreadmeファイルを書いて、完成とします!
よりハイレベルな何かを勉強して、その知識を使って何かを作り上げるのは非常に楽しいです。
おそらくこれが僕の本質だと思います。
このwebアプリの作成を通して得られた知見
まとめとして、このwebアプリの作成を通して得られた知見は以下です
gitのシステムのより深い理解と様々な使い方(ブランチの概念、originの概念、マージの概念、コマンドの使い方:checkout , add , commit, merge , barnch , reflog ,reset、各種オプション、やらかした際の復旧方法etc...,)
チーム開発を意識した、githubのより突っ込んだ使い方の会得(タスクのissue管理 , issueと連帯させたプルリクやcommitの発行(マージされたらIssueもcloseされる)
各モデルのリレーションシップや、外部ライブラリ等データの使用目的に合わせた保存するべきデータの内容等から考えた、0からの自作モデル設計
各モデルや各コントローラとの関連性も考えたURLやルーティング等の設計(resourceの入れ子構造など)
ominiauthを使った、TwitterOAuth認証の実装方法とテスティングの方法(テスト方法が分かるまでほんと長かった…)
ビューとモデルに合わせたコントローラの条件分岐の実装方法
バグの原因を潰すための、before_actionを使ったコントローラのアクセス制限
コントローラにおけるDBデータオブジェクトの取扱い
グラフ描画用ライブラリchartkickの使い方と実装方法。
chartkickで扱えるようにDBの複数カラムのデータを加工して配列にして渡す、自作メソッドの実装と文字列操作の方法。
セレクトメニューの使い方と実装方法
seedsファイルの設定方法
条件分岐や、ログインユーザーとアクションの関係性を考えた単体テストと統合テスト
httpメソッド(post get,delete等)のオーソドックスな使い方のや、セッションの扱い方の復習
正直他にも書ききれないぐらい細かい知識やノウハウを得られました。
作りたいものや使ってみたい技術の構想はいくつもあるので、またぼちぼち作ってスキルアップしていこうと思います。