自己紹介
業務委託でestieに参画している@HirokiOmoteです。
estieでは主にデザインとFrontendを担当しています。
過去には、スタートアップの創業フェーズでプロダクトの立ち上げなども行なっていました。
そこでは、Nuxt + Firebaseを採用し、Webアプリの制作に着手。
しかし、プロダクトが成長するにつれ、コードの安全性や可読性の観点からJavaScript…動的型付け言語の限界を感じていました。
そして、静的型付け言語であるTypeScriptを採用することに。
また、Firebase Cloud Functionsを使った機能開発も行うようになり、次第にBackendもTypeScriptを使って書くようになりました。
それが、TypeScriptとの出会いです。
気づけば、すっかりその魅力に取りつかれていました。TypeScriptは楽しい。
そもそもTypeScriptとは
「Type」と名のつくように、Type=型によるチェックが可能です。
そのため、プログラムの可読性の向上やバグの発見が容易になるため、リリース前後の修正コストを抑えることができます。
Airbnbでは、TypeScriptを採用後、38%ものバグを未然に防ぐことができたとか。
TypeScriptはMicrosoftによって開発されたオープンソース言語であり、Visual Studio Codeによる補完がよく効くのも快適な開発体験の一助になっています。
また、TypeScriptはJavaScriptの最新仕様が使える上方互換(スーパーセット)でもあるので、型について深く知らなくても、モダンなJavaScriptの書き味を体験できるという点だけで、面白さがあるのではないでしょうか。(optional chainingとか)
型推論もありますし、JavaScriptとそう変わらないコード量になることも多いですね。
ReactやVueなどのモダン・フロントエンドでも、TypeScriptの親和性は年々高まっていますが、DenoやNode.js(ts-node)でも対応しているため、BackendでもTypeScriptを採用するケースが増えているようにも感じます。Next.jsやNuxtならTypeScriptだけでフルスタックに作っていけますね。
どんな時に使うか
主に以下の様なメリットを感じています。
- リアルタイムでエラーを指摘してくれる(Visual Studio Code)
- Componentでpropsの中身がわかりやすい
もちろん、estieでもFrontendではTypeScriptの導入を積極的に行なっています! estieではReact、Vueのどちらも採用されていますが、今回はReactを軸に解説していきたいと思います。
Figmaでのボタンのデザイン例
FigmaでAtomicButtonというコンポーネントを作りました。
primary
secondary
danger
の3種類の出し分けができるように、Propertiesを設定。
これらをReactでコーディングします。CSSは割愛。
JavaScript(JSX)
import React from "react"; export default function AtomicButton(props) { return ( <div className={ props.type || 'primary' }> <button disabled={ props.disabled }>{ props.text }</button> </div> ) }
propsに何が入ってくるのか分かりません。
そのため、AtomicButtonというコンポーネントにどんな機能があるか把握しにくいですね。
タイプミスで不用意にprops.hoge
にアクセスして、undefined
が返されるケースもありそうです。
心臓に悪いです…。
TypeScriptで型をつけてみる
いよいよTypeScriptに挑戦です! 簡単に型をつけてみましょう。
今回、大事なのはFigmaで設計したPropertyをtype Propsとして再現することです。
TypeScript(TSX)
import React from "react"; type Props = { text: string // Buttonテキスト disabled?: boolean // Disabled属性を付与 mode?: 'primary' | 'secondary' | 'danger' // ボタンの種類の出しわけ } export default function AtomicButton(props: Props) { return ( <div className={ props.type || 'primary' }> <button disabled={ props.disabled }>{ props.text }</button> </div> ) }
型を明示するだけで、text
とmode
の役割が少し明るくなりました。
text
の型はあらゆる文字列が入力できるstring型に指定します。
mode
の型ははUnion型と言います。'primary' | 'secondary' | 'danger'
のいずれかの文字が入ってくることを示しています。
disabledはboolean型で、<button>
タグにdisabled属性をつけられるようにもしています。
また、type?
、disabled?
はoptional型で省略可能を示しています。
こうすることで、コンポーネントを<button>
の挙動と同じになる様に拡張することもできますね。
特にAtomic Designでは、Atomsの様に小さく汎用的なコンポーネントほど多機能になり、Propsが肥大していくこともしばしば。
プロダクトによっては、その数が30を超えるケースもあるそうです。
だからこそ、Figma・TypeScript間での設計はかなり重要です。
逆に言えば、役割が整然されたデザインは、プロダクトや会社にとっての資産になり得ると考えています。
一貫性のあるものは美しいですね。
最後に型クイズ
前項でもお伝えしましたが、TypeScriptはJavaScriptのスーパーセットであるので、型も必要最低限の知識で十分使っていけます。
とはいえ、 複雑なstateの設定や関数を作成する際、上手く設計や型がハマった場合に、とても気持ちがいいです。
それではここでクイズ。 ???を満たすTypeを探してみましょう!
Q1
export const q1 : A1 = 'text1' export const q1_2 : A1 = 1 type A1 = ???
Q2
const q3 = (value : A3) => { console.log(`${value} World!`) } q3('Hello') q3('GoodBye') q3('Seeyo') // compile error type A3 = = ???
Q3
export const q4 : A6 = 'text' export const q5 : A6 = 1 export const q6 : A6 = true type Union<T, U> = T | U type A4 = ??? type A5 = ??? type A6 = Union<???>
Q4
type stringArray = ['first', 'middle', 'second'] type numberArray = [1, 2, 3] type stringFirst = First<stringArray> // firstを返す type number2 = First<numberArray> // 2を返す type First<T> = ???
まとめ
- TypeScriptはモダンJavaScriptに型をつけたもの
- コンポーネントの状態管理(state)だけでも使っていける
- パズルゲーム的な面白さもある
最後までご覧下さいまして、ありがとうございました!
estieはデザイン~エンジニアリングの垣根を超えて働ける場所で、とても楽しいです。
興味をお持ちの方は、デザイン、Frontend、Backend問わず、ぜひお話ししましょうー!
(もちろん答え合わせも!)
Twitterからも、是非、ご連絡ください。 表洋樹 / estie (@HirokiOmote) / Twitter
またはこちらから!