Hatena::ブログ(Diary)

rikubaの日記 RSSフィード

 

2018-02-02

特定のプロパティを除外した新しいオブジェクトを作る(immutableなdelete)

あるオブジェクトから、特定のプロパティのみ除外した新しいオブジェクトを作りたい場合がある。

const p1 = {
  x: 0,
  y: 1,
  z: 2,
};

// p1からzプロパティを除外した新しいオブジェクトを作る

const p2 = Object.assign({}, p1);
delete p2.z;

console.log(p2); // { x: 0, y: 1 }


最近の実装(およびtranspile前提の環境)であればECMAScriptのObject Rest Destructuringを使うことで、外部ライブラリやユーティリティ関数を用意しなくても1行で書くことができる。

const { z, ...p2 } = p1;

console.log(p2); // { x: 0, y: 1 }


格納されるプロパティのキーや取り除きたいプロパティのキーが動的な場合は、ComputedPropertyNameと組み合わせることになる。

const key = 'z';

const { [key]: _, ...p2 } = p1;

console.log(_); // 2
                // うーん……


取り除かれたプロパティの値は使わないよという表明で`_`にしたけど、そもそも余計な定数が定義されないようにしたい。そこでさらに空の分割代入を行う。

const key = 'z';

const { [key]: {}, ...p2 } = p1; // {}の代わりに[]でも可

// 不要な定数は定義されない!


これでよし!と思いきや、keyのプロパティが存在しなかったり、値がundefinedだった場合にエラーが起きてしまう。

const p1 = {
  x: 0,
  y: 1,
};

const key = 'z';

const { [key]: {}, ...p2 } = p1; // TypeError: p1[(intermediate value)] is undefined


ということでデフォルト値を指定する。

const p1 = {
  x: 0,
  y: 1,
};

const key = 'z';

const { [key]: {} = {}, ...p2 } = p1; // 問題なし!

これでよし!ただし、プロパティの値がnullの場合はデフォルト値が採用されず、先ほどと同様にTypeErrorが投げられてしまうので、値にnullが含まれ得るオブジェクトには使えない。


そのままreturnする場合などは、IIFEで引数をdestructuringすれば1文で書けるけど、ここまでくるとさすがにやりすぎな感じがする。

switch (action.type) {
  case 'PAGE_CLOSE':
    return (({ [action.id]: {} = {}, ...nextState }) => nextState)(state);

  // ...
}

書き捨てではない・読まれるコードでは、lodash/fpomitなどを使おう……。


TypeScriptでもちゃんと型がomitされて幸せ。

f:id:rikuba:20180202021239p:image


とはいえもう型のomitも表現できるようになってるけど。

2018-01-22

TypeScriptでReduxのActionを書くときの煩わしさを軽減するためのモジュールを作った

TypeScriptで型の恩恵を受けられるようにReduxアプリケーションのコードを書こうとすると、同じようなことを繰り返し書かなければならないところがある。顕著なのはAction周りだと思う。同じことを思う人が多いのか、既に楽に書くためのモジュールがたくさんある(ts-action, typescript-fsa, typesafe-actions, などなど)けど、Middlewareが必要だったり、Reducerの書き方を変えなければならなかったりしてどれもしっくりこない。

もっとシンプルに解決できないかなと思ってモジュールを作ってみた。実装としてはTypeScriptで14行、提供するのは2つのAPIのみ。

以下、Redux Async Exampleの例を借りて、pureにTypeScriptで書いたコードとこのモジュールを使って書いたコードを比較してみる。

続きを読む

2016-06-22

ホイール操作でスライドをめくるユーザースクリプト

以前作ったslideshare scrollというユーザースクリプトでQiitaのスライドにも対応しようと思ったものの、3年前のコードで無駄が多いので一から書き直した。

createWheelHandlerで前後ボタンの取得を遅延させているのは、Qiitaのスライドが非同期で組み立てられるため。

2016-06-08

GitHub上のJSコードでモジュールをリンクで辿れるようにするユーザースクリプト

OctoLinkerという、より高機能な拡張機能が既に存在した。

を作った。GitHub上でのコードリーディングが少し楽になる(じっくり読むならgit clone)。

f:id:rikuba:20160608190258p:image

続きを読む

2014-05-31

JavaScriptでgetterとsetterのどちらか一方のみをオーバーライドする

JavaScript でオブジェクトに accessor property を定義したとき、継承先でそのプロパティの getter, setter のどちらか一方のみを override するのは一筋縄にはいかない。

例として、長方形を表す Rectangle と、正方形を表す Square を定義することを考える。SquareRectangle を継承する。

続きを読む

 
プロフィール

rikuba

JavaScript/TypeScriptで遊んでいます