Atomic Design
現在開発中のサービスにおいて
既存のAtomic Design に沿ったコンポーネント設計をしております。
Atomic Design がよくわからなかったのでメモしていきます。
そもそもatomic Design とは
Atomic design is methodology for creating design systems. There are five distinct levels in atomic design: Atomic design はデザインシステムを構築するための手段(方法論)です。大きさのレベルに応じて5つの要素に分類できます。
Atoms, Molecules, Organisms, Templates, Pages それらは Atoms, Molecules, Organisms, Templates, Pages の五つです。
つまり、Atomic DesignはUIを構成するコンポーネントを5つのコンポーネントレベルに分け、
その五つを組み合わせることで全てのUIを表現する手法のことです。
(参照: https://bradfrost.com/blog/post/atomic-web-design/)
単一責任の法則
「モジュールが持つ責務は一つにすべき」という考え方のこと。
Atomic Design でいうところの Atomに一つの責務を置き、それらを組み合わせてアプリケーションを開発する。
分割統治法
「大きな課題を小さく分割することで課題解決をしていく」という考え方。
最近コンポーネント設計をしていて、
単一責任の法則も分割統治法も「コンポーネント一つのタスクを最小限にして問題解決、リファクタしやすくする」
ための基本の考え方みたい。
哲学っぽくて面白い。。
参考
https://zenn.dev/offers/articles/20220523-component-design-best-practice
【typescript】sortを利用して配列を並び替える
sort()メソッドは、配列の要素をソートする関数のこと。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
一般的なuse case
配列にsort() を実行すると昇順に並び替えてくれます。
定義した配列そのものが変更されているので、破壊的変更が加わっていることになります。
const nameList = ["Batto","Atsuki","chieko","Den"]; console.log(nameList.sort()) //["Atsuki", "Batto", "Chieko", "Den"]
非破壊的ソート
nameList.sort()だと、nameListそのものの配列の順序が変わってしまいます。
それだとイミュータブルの観点からデバックしにくくなってしまいます。
残余構文を利用して、以下のように書き換え
const nameList = ["Batto","Atsuki","chieko","Den"]; const newNameArray = [...nameArray].sort() //newNameArray → ["Atsuki", "Batto", "Chieko", "Den"] //nameArrayはそのまま
ミューテーションについてはこちらの関数型プログラミングお姉さんの動画がおすすめ(笑)
https://www.youtube.com/watch?v=e-5obm1G_FY
比較関数
実はsort()の第一引数に関数を追加することで並び順を制御することができます。
デフォルトの昇順は以下のような比較関数になります。
nameList.sort((a,b) => a + b) //昇順
そして降順は
nameList.sort((a,b) => a - b) //昇順
配列の中身をオブジェクトにし、特定の値でソート
以下のようなオブジェクトでもソートできるということ。。。すごいですよね、、
const stations = [ {name: "池袋", users: 55223}, {name: "新宿", users: 10000}, {name: "渋谷", users: 300}, {name: "東京", users: 400000}, ] const stationsOriginal = stations.sort((a, b)=> a.users - b.users) //結果 const stations = [{ "name": "渋谷", "users": 300 }, { "name": "新宿", "users": 10000 }, { "name": "池袋", "users": 55223 }, { "name": "東京", "users": 400000 }] //うおおお
【typescript】配列の二列目以降の取り出し
今まではsplice(num)などを利用して
配列を切り分けて取り出していたのですが、最近はもっと直感的な取り出し方があるみたいです。
まとめて取り出し
配列があります
const smalls = [ "小動物", "小型車", "小論文" ];
まとめて取り出すことも可能!!
const [a, b , c] = smalls; //a = '小動物
スプレッド構文を用いて、一番目以降の配列を取得します。
const [, ...other] = smalls; //["小型車", "小論文"]
新しい配列を作るときは左辺に代入していくのではなく、右辺で配列を直接作って代入する。
const smallsAnime = [ "コナン君", "小次郎" ] const newArray= [...smalls(slice(0,2),"小売業"],...smallsAnime )] //[ "小動物", "小型車", "小売業", "コナン君", "小次郎"]
直感できでわかりやすい、、これから使ってみよう。
【Typescript】Partial<T> ついて
今日はUtility Typesについて学んだので、その学習メモ。
さまざまなユーティリティーがあるが、その一つを例にとってみると少し理解が深まりました。
今回はPartialについて。
Utilty Types とは
Typescriptが提供する型の関数のようなもの。
元のインターフェースを利用し、新しい型を作成することができる。
Partial
それぞれのプロパティをoptionalにしたいときに利用する。
//インターフェースがあります interface Todo { title: string; description: string; } //インターフェースTodoをもつtodo1 const todo1: Todo = { title: "orgnize desk", description: "clear clutter", } //アップデートするための関数 function updateTodo(todo: Todo, fieldsTodUpdate: Partial<Todo>){ return {...todo, ...fieldsTodUpdate}; } //updateTodoを利用し第一引数にコピーしたいオブジェクト、第二引数に追加したいオブジェクトを追加 const todo2 = updateTodo(todo1, {description: "throw out trash",})
この時、updateTodoの第二引数の型を
Partial<Todo>
にすることで、「Todoのプロパティーのうちどれか」を実現することができます。
終わり
こんな感じで、ユーティリティーを使うと元々のインターフェースを加工した型を表現することが可能です。
他にも特定のインターフェースを減らしたり、増やしたり、レコードを作成したり、色々できるみたいなので
現場のコードと照らし合わせつつ勉強していこうと思います。
参考
https://www.typescriptlang.org/docs/handbook/utility-types.html
【Typescript】型ガードについて
型ガード(Type guard)について
if分やcase文を始めたとした条件分岐で変数の方を判別し、ブロック内の変数の型を絞り込む機能のこと。
型を変数内で明示して変換する「キャスト」を使用することを防げる。
type of
変数の型をチェックできます。
type You = string const you: You = "kotaro"; console.log(typeof You) // string
型がstringとnumberの合併型の場合は、stringにしか使えないメソッドを使うとエラーになる
type NumOrStr = number|string ; function useSomeNumOrStr (arg:NumOrStr): NumOrStr { const toUpperCaseStr = arg.toUpperCase() return toUpperCaseStr } //Property 'toUpperCase' does not exist on type 'NumOrStr'. //Property 'toUpperCase' does not exist on type 'number'.
typeof の結果を条件分岐してあげることでエラーを回避できる
type NumOrStr = number|string ; function useSomeNumOrStr (arg:NumOrStr): NumOrStr { if (typeof arg === "string") { const toUpperCaseStr = arg.toUpperCase() return toUpperCaseStr } return arg }
【Typescript】オブジェクトのキーの文字列のみを許容する動的な型宣言
オブジェクトのキーをオブジェクトの型のプロパティーとしてそのまま流用したい場合。
まず、オブジェクトの型を定義したい場合
type Panda = { age: number } const panda: Panda = { age: 11, } //型通り
そのオブジェクトのキーをage, name, color, dream のいずれかにしたい場合
type Panda = {[K in 'age'|'name'|'color'|'dream']: string} const panda: Panda = {age: "fifty five" ,name: "Eric Clapton",color: "red", dream: "change the world"}
インターフェースのオブジェクトのキーを次の型のプロパティーにする
type Panda = { age: number; name: string; dream: string; } type Pandaaaa = {[K in keyof Panda]: string} // Panda型のキーがPandaaaaのプロパティーとして使える
上記のように、オブジェクトのキーも特定の文字だけしか入らないようにすることが可能。
特に [K in keyof Object]
と記述し、オブジェクトのプロパティを指定したり、
[K in 'A'|'B'|'C']
と記述し、特定のキーを直書きすることができる。
【Typescript】extendsを用いてジェネリクスの型パラメータに制約をつける
ジェネリクスで型定義をする際に、特定のプロパティーを持たせるように制限することができる。
引数に存在しないプロパティーがある場合
function showBirthday<T>(person: T): Date { const birthDay = person.getBirthDay(); // personの型は未知なのでgetBirthDay()メソッドがあるかどうか未定でエラーになる return birthDay; } //error : Property 'getBirthDay' does not exist on type 'T'. //TにgetBirthDayなんてプロパティーは存在しません!!
extendを利用して型推論時に「引数に特定のプロパティーが存在する」ように制約をつける
type Person = { getBirthDay(): Date; } function showBirthDay<T extends Person>(person: T): Date { const birthDay = person.getBirthDay(); return birthDay } // ok !!