Skip to content

Instantly share code, notes, and snippets.

@otofu-square
Last active August 30, 2017 06:09
Show Gist options
  • Save otofu-square/7a9f4490a87184894dc7e747e4445b79 to your computer and use it in GitHub Desktop.
Save otofu-square/7a9f4490a87184894dc7e747e4445b79 to your computer and use it in GitHub Desktop.
Dynamic check types of the object values in TypeScript with ramda
import {
all,
curry,
equals,
isNil,
mapObjIndexed,
pipe,
propSatisfies,
values,
} from "ramda";
const isNumber = (v: any) => typeof v === "number";
const isString = (v: any) => typeof v === "string";
const isArray = (v: any) => Array.isArray(v);
// オブジェクトの動的型チェックをするための定義オブジェクト
interface IObjectDefinition {
[key: string]: (_: any) => boolean;
}
const checkObj = curry((definition: IObjectDefinition, obj: any) =>
pipe<any, any, any, any>(
// IObjectDefinition からキーと、値のチェックを行う関数を取り出して、実際に検証するオブジェクトをチェックした結果(true, false)をマッピングする
mapObjIndexed(
(val: (_: any) => boolean, key: string) =>
isNil(obj[key]) ? false : propSatisfies(val, key, obj),
) as any,
// 検証結果(true, false)をマッピングしたオブジェクトから値だけのリストを作成する
values,
// 全て true かどうかチェックする
all(equals(true)),
)(definition),
);
// 1引数をとってその値を検証した結果の Boolean を返す関数のオブジェクトを定義する
const myObjDef: IObjectDefinition = {
a: isNumber,
b: isString,
c: isArray,
d: checkObj({
e: isNumber,
f: isString,
}),
};
const checkMyObj = checkObj(myObjDef);
// 定義されたキーと、そのキーに対する値の検証が全て通れば true
const myObj = {
a: 1,
b: "string",
c: [],
d: {
e: 10,
f: "This is string.",
},
};
console.log(checkMyObj(myObj)); // => true
// 検証に失敗する値がオブジェクトに入っている場合は false を返す
const invalidObj1 = {
a: null,
b: "string",
c: {},
d: {
e: 10,
f: "This is string.",
},
};
console.log(checkMyObj(invalidObj1)); // => false
// オブジェクトのキーが不足している場合も false が返る
const invalidObj2 = {
a: 1,
};
console.log(checkMyObj(invalidObj2)); // => false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment