LoginSignup
0
1

More than 5 years have passed since last update.

TypeScriptとlodashで型安全なネストしたobjectのimmutableな更新を手に入れる

Posted at

元ネタ

TypeScriptのすごいひとすごい。

今回はこの型付け方法を参考にlodashのsetとupdateに型を付けます。

またImmutableなobjectの更新をしたいので内部でlodash/fpを使いますが引数の順序は普通のlodashに合わせています。

/* tslint:disable:max-line-length */
const _ = {
    set: require('lodash/fp/set'),
};

function set<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], K5 extends keyof O[K1][K2][K3][K4], K6 extends keyof O[K1][K2][K3][K4][K5], K7 extends keyof O[K1][K2][K3][K4][K5][K6], K8 extends keyof O[K1][K2][K3][K4][K5][K6][K7], K9 extends keyof O[K1][K2][K3][K4][K5][K6][K7][K8], K10 extends keyof O[K1][K2][K3][K4][K5][K6][K7][K8][K9], V>(obj: O, path: string | [K1, K2, K3, K4, K5, K6, K7, K8, K9, K10], val: V): O & Record<K1, Record<K2, Record<K3, Record<K4, Record<K5, Record<K6, Record<K7, Record<K8, Record<K9, Record<K10, V>>>>>>>>>>;
function set<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], K5 extends keyof O[K1][K2][K3][K4], K6 extends keyof O[K1][K2][K3][K4][K5], K7 extends keyof O[K1][K2][K3][K4][K5][K6], K8 extends keyof O[K1][K2][K3][K4][K5][K6][K7], K9 extends keyof O[K1][K2][K3][K4][K5][K6][K7][K8], V>(obj: O, path: string | [K1, K2, K3, K4, K5, K6, K7, K8, K9], val: V): O & Record<K1, Record<K2, Record<K3, Record<K4, Record<K5, Record<K6, Record<K7, Record<K8, Record<K9, V>>>>>>>>>;
function set<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], K5 extends keyof O[K1][K2][K3][K4], K6 extends keyof O[K1][K2][K3][K4][K5], K7 extends keyof O[K1][K2][K3][K4][K5][K6], K8 extends keyof O[K1][K2][K3][K4][K5][K6][K7], V>(obj: O, path: string | [K1, K2, K3, K4, K5, K6, K7, K8], val: V): O & Record<K1, Record<K2, Record<K3, Record<K4, Record<K5, Record<K6, Record<K7, Record<K8, V>>>>>>>>;
function set<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], K5 extends keyof O[K1][K2][K3][K4], K6 extends keyof O[K1][K2][K3][K4][K5], K7 extends keyof O[K1][K2][K3][K4][K5][K6], V>(obj: O, path: string | [K1, K2, K3, K4, K5, K6, K7], val: V): O & Record<K1, Record<K2, Record<K3, Record<K4, Record<K5, Record<K6, Record<K7, V>>>>>>>;
function set<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], K5 extends keyof O[K1][K2][K3][K4], K6 extends keyof O[K1][K2][K3][K4][K5], V>(obj: O, path: string | [K1, K2, K3, K4, K5, K6], val: V): O & Record<K1, Record<K2, Record<K3, Record<K4, Record<K5, Record<K6, V>>>>>>;
function set<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], K5 extends keyof O[K1][K2][K3][K4], V>(obj: O, path: string | [K1, K2, K3, K4, K5], val: V): O & Record<K1, Record<K2, Record<K3, Record<K4, Record<K5, V>>>>>;
function set<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], V>(obj: O, path: string | [K1, K2, K3, K4], val: V): O & Record<K1, Record<K2, Record<K3, Record<K4, V>>>>;
function set<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], V>(obj: O, path: string | [K1, K2, K3], val: V): O & Record<K1, Record<K2, Record<K3, V>>>;
function set<O, K1 extends keyof O, K2 extends keyof O[K1], V>(obj: O, path: string | [K1, K2], val: V): O & Record<K1, Record<K2, V>>;
function set<O, K1 extends keyof O, V>(obj: O, path: string | [K1], val: V): O & Record<K1, V>;
function set<O, K1 extends keyof O, V>(obj: O, path: string | K1, val: V): O & Record<K1, V> {
    return _.set(path, val, obj);
}
/* tslint:disable:max-line-length */
const _ = {
    update: require('lodash/fp/update'),
};

function update<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], K5 extends keyof O[K1][K2][K3][K4], K6 extends keyof O[K1][K2][K3][K4][K5], K7 extends keyof O[K1][K2][K3][K4][K5][K6], K8 extends keyof O[K1][K2][K3][K4][K5][K6][K7], K9 extends keyof O[K1][K2][K3][K4][K5][K6][K7][K8], K10 extends keyof O[K1][K2][K3][K4][K5][K6][K7][K8][K9], V>(obj: O, path: string | [K1, K2, K3, K4, K5, K6, K7, K8, K9, K10], updater: (v: O[K1][K2][K3][K4][K5][K6][K7][K8][K9][K10]) => V): O & Record<K1, Record<K2, Record<K3, Record<K4, Record<K5, Record<K6, Record<K7, Record<K8, Record<K9, Record<K10, V>>>>>>>>>>;
function update<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], K5 extends keyof O[K1][K2][K3][K4], K6 extends keyof O[K1][K2][K3][K4][K5], K7 extends keyof O[K1][K2][K3][K4][K5][K6], K8 extends keyof O[K1][K2][K3][K4][K5][K6][K7], K9 extends keyof O[K1][K2][K3][K4][K5][K6][K7][K8], V>(obj: O, path: string | [K1, K2, K3, K4, K5, K6, K7, K8, K9], updater: (v: O[K1][K2][K3][K4][K5][K6][K7][K8][K9]) => V): O & Record<K1, Record<K2, Record<K3, Record<K4, Record<K5, Record<K6, Record<K7, Record<K8, Record<K9, V>>>>>>>>>;
function update<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], K5 extends keyof O[K1][K2][K3][K4], K6 extends keyof O[K1][K2][K3][K4][K5], K7 extends keyof O[K1][K2][K3][K4][K5][K6], K8 extends keyof O[K1][K2][K3][K4][K5][K6][K7], V>(obj: O, path: string | [K1, K2, K3, K4, K5, K6, K7, K8], updater: (v: O[K1][K2][K3][K4][K5][K6][K7][K8]) => V): O & Record<K1, Record<K2, Record<K3, Record<K4, Record<K5, Record<K6, Record<K7, Record<K8, V>>>>>>>>;
function update<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], K5 extends keyof O[K1][K2][K3][K4], K6 extends keyof O[K1][K2][K3][K4][K5], K7 extends keyof O[K1][K2][K3][K4][K5][K6], V>(obj: O, path: string | [K1, K2, K3, K4, K5, K6, K7], updater: (v: O[K1][K2][K3][K4][K5][K6][K7]) => V): O & Record<K1, Record<K2, Record<K3, Record<K4, Record<K5, Record<K6, Record<K7, V>>>>>>>;
function update<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], K5 extends keyof O[K1][K2][K3][K4], K6 extends keyof O[K1][K2][K3][K4][K5], V>(obj: O, path: string | [K1, K2, K3, K4, K5, K6], updater: (v: O[K1][K2][K3][K4][K5][K6]) => V): O & Record<K1, Record<K2, Record<K3, Record<K4, Record<K5, Record<K6, V>>>>>>;
function update<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], K5 extends keyof O[K1][K2][K3][K4], V>(obj: O, path: string | [K1, K2, K3, K4, K5], updater: (v: O[K1][K2][K3][K4][K5]) => V): O & Record<K1, Record<K2, Record<K3, Record<K4, Record<K5, V>>>>>;
function update<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], K4 extends keyof O[K1][K2][K3], V>(obj: O, path: string | [K1, K2, K3, K4], updater: (v: O[K1][K2][K3][K4]) => V): O & Record<K1, Record<K2, Record<K3, Record<K4, V>>>>;
function update<O, K1 extends keyof O, K2 extends keyof O[K1], K3 extends keyof O[K1][K2], V>(obj: O, path: string | [K1, K2, K3], updater: (v: O[K1][K2][K3]) => V): O & Record<K1, Record<K2, Record<K3, V>>>;
function update<O, K1 extends keyof O, K2 extends keyof O[K1], V>(obj: O, path: string | [K1, K2], updater: (v: O[K1][K2]) => V): O & Record<K1, Record<K2, V>>;
function update<O, K1 extends keyof O, V>(obj: O, path: string | [K1], updater: (v: O[K1]) => V): O & Record<K1, V>;
function update<O, K1 extends keyof O, V>(obj: O, path: string | K1, updater: (v: O[K1]) => V): O & Record<K1, V> {
    return _.update(path, updater, obj);
}

10段階のネストまで対応してます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1