
TSを何故使うのか?と言われると、「Javascriptを一段上のレベルでプログラミングしたいから」と言うのは変ですか?
「より安全なプログラミングをしたい。」とか「他の言語に対して親和性を持たせたい」とか
色々な思考が過りますが、個人的には、「何となくカッコいいから」も、ベスト解のような気がします。
いいじゃん、見た目もスタイルも重要なモチベーションですよ。
そんなワケで、今回は「TSらしい書き方のパターン」というのを学習して、モチベをアップさせてみたいと思います。
TSっぽさについて考える
TSっぽさ=「型が助けてくれる設計」に寄せることではないかと思う。
そのためのパターンを覚える(使えるようになる)事がTSらしいコーディングなのではないかと考えてみました。
とりあえず、覚えて、書いてみて、身につけていく精神で学習を進めた方がいいので、今回は、パターンを列挙してみます。
型を直接書くパターン
関数の外から参照される変数
仕様が変わっても安全&可読性UPする。
const taxRate: number = 0.1
関数の引数・戻り値
仕様・APIを固定できるのが特徴。
function calc(price: number): number {
return price * 1.1
}
型推論パターン
代入時に型が確定する場合は書かない
let count = 0 // number推論される
const message = "hello" // string
オブジェクトで型が推論可能なケース
const user = {
id: 1,
name: "taro"
}
// user.id: number, user.name: string
型エイリアス & interface(共通化フェーズ)パターン
同じ構造を複数箇所で使う時
type User = {
id: number
name: string
}
function print(user: User) {
console.log(user.name)
}
拡張の可能性がある場合は interface が向いてる
interface Base {
id: number
}
interface Admin extends Base {
role: "admin"
}
Union / Literal (選択肢で縛る)型パターン
状態や種別を "string じゃなく用途で縛りたい時"
type Status = "pending" | "done" | "error"
const state: Status = "pending"
Generics(型を渡す設計)パターン
共通ロジックに型のバリエーションを持たせたい時
function wrap<T>(value: T): T[] {
return [value]
}
const a = wrap(1) // number[]
const b = wrap("hi") // string[]
readonly / const assertion(意図の固定化)パターン
変わらないことを型に刻む
const config = {
mode: "production",
port: 3000,
} as const
// mode: "production" (literal確定)
Narrowing(型で条件分岐)パターン
TS特有。runtimeチェック+型確定
function describe(value: number | string) {
if (typeof value === "number") {
return value.toFixed(2) // number扱いに絞られる
}
return value.toUpperCase() // string扱い
}
TSらしいコード思想
・書けるときは型を書かない(推論に任せる)
・書くべきところには明示する(境界面/API/仕様部分)
・型をDRYにし、再利用性と変更耐性を持たせる
・型で「意図」を表現する(Literal, Union, readonly, Generics)
・runtimeチェックと型 narrowing をセットで考える
あとがき
概ね、今回のパターンを覚えておくと、TSを理解できて、実際に使えるレベルだと思ってもいいでしょう。
個人的には、TS特有の機能を使いたいわけではなく、別のコンパイル言語と同じような書き方ができることで、親和性を持たせる(=同時にコーディングするときの思考コンフリクトを無くす)事が重要だと考えてます。
あとは、開発コーディングの時に、画面確認するたびにコンパイルするのがめんどくさそうだな〜とか考えてますが、この辺の慣れも必要かもしれませんね。
0 件のコメント:
コメントを投稿