types.js — Javascript библиотека для управления типами

Доброго времени суток!
Недавно я решил упростить себе жизнь и написать библиотеку для работы с типами данных. Так получилась types.js.
Библиотека самостоятельна и не требует никаких других.

Что умеет

  • Описывать типы
  • Валидировать аргументы
  • Перегружать методы

Регистрация типов

Библиотека умеет регистрировать типы данных в достаточно удобной форме

<code class="javascript">    types.register("Array", {
        // метод для тестирования значения
        test: function(value) {
            return value instanceof Array;
        },
        // Тип может быть контейнером для других значений, например массив. Но также это может быть
        // что-то вроде сеттера-геттера (как observable из knockoutjs), поэтому мы не можем знать, как перебрать или достать эти 
        // самые значения. Этот метод должен быть, если мы хотим уметь тестировать значения внутри типа
        valueTest: function(object, type) {
            for(var i = 0, l = object.length; i < l; i++) {
                if(!types.test(type, object[i])) {
                    return false;
                }
            }
            return true;
        },
        // значение по-умолчанию
        defaultValue: function() {
            return [];
        }
    });

    types.test("Array", []); // true
    types.test("Array", {}); // false

    types.get("Array").test([]); // true
    types.get("Array").test({}); // false
    
    // Проверить, все ли значения в массиве типа Number
    types.get("Array").testValue([1, 2, 3, 4], "Number"); // true
    types.get("Array").testValue(["1", "2", "3", "4"], "Number"); // false
    
    // получить значение по-умолчанию
    types.get("Array").getDefault(); // []
</code>

types.test также может принимать первым аргументом массив с именами типов, и будет проверять значение на соответсвие хотя бы одному из типов.

<code class="javascript">    types.test(["Number", "Boolean", "String"], 1); // true
    types.test(["Number", "Boolean", "String"], false); // true
    types.test(["Number", "Boolean", "String"], "1"); // true
    types.test(["Number", "Boolean", "String"], new Date()); // false
</code>

Валидация аргументов

Для этого нужно просто создать валидатор, передав в него массив с описанием типов

<code class="javascript">var myValidator = new types.Validator([
    // first value should be a number
    {
        type: "Number"
    },
    // second value should be an Array of numbers
    {
        type: "Array",
        of: "Number"
    },
    // third value should be a number or an Array of strings
    {
        type: ["Number", "Array"],
        of: "String"
    },
    // fourth value should pass a custom test
    {
        type: function(value) {
            return value == "uf-uf";
        },
    }
]);
</code>

Либо в сокращённой нотации

<code class="javascript">var myValidator = new types.Validator([
    "Number",
    // type:of, array of numbers
    {"Array": "Number"},
    // number or array of strings
    ["Number", {"Array": "String"}],
    // custom test
    function(value) {
        return value == "uf-uf";
    }
]);
</code>

И использовать, передавая массив или arguments.

<code class="javascript">// 0 - number, 1 - array, 2 - number, 3 - "uf-uf" - всё ок
myValidator.test([1, [2], 3, "uf-uf"]); // true
// массив содержит не только number
myValidator.test([1, [2, ""], 3]); // false
// третий агрумент может быть либо числом, либо массивом строк
myValidator.test([1, [2], [3], "uf-uf"]); // false
// тут всё хорошо
myValidator.test([1, [2], [""], "uf-uf"]); // true
</code>

Перегрузка

Последняя, не менее важная возможность библиотеки — обёртка для упрощения создания перегруженных методов.
Всё, что нужно, создать метод, передав в волшебную функцию types.overload массив, где по чётным — сигнатуры, по нечётным — методы.

<code class="javascript">var simple = types.overload([
    // Если передать число и строку
    ["Number", "String"],
    function(age, name) {
        return 1;
    },
    
    // Если передать массив, boolean и строку
    ["Array", "Boolean", "String"], 
    function(list, isMad, name) {
        return 2;
    }
],
// в каком контексте будут вызываться методы 
this);

simple(1, "Vasia"); // 1
simple([], true, "Vasia"); // 2
</code>

Если в конце ещё передать одинокую функцию, то она вызовется после выполнения функцию с нужной сигнатурой, и принимать должна её результат.

<code class="javascript">// overloading with 'final' metod
var withFinal = types.overload([
    ["Number", "String"], 
    function(age, name) {
        return 1;
    },

    ["Array", "Boolean", "String"], 
    function(list, isMad, name) {
        return 2;
    },

    // final method
    function(num) {
        if(num === 1) {
            return true;
        } else {
            return false;
        }
    }
],
// scope 
this);

withFinal(1, "Vasia"); // true
withFinal([], true, "Vasia"); // false
</code>

Типы «из коробки»

  • Any
  • Array
  • Function
  • Number
  • Numeric (не NaN и не Infinity, тольк тру числа)
  • String
  • Boolean
  • Date
  • Regexp
  • Object
  • Timestamp
  • TimestampM (13-ти значный валидный таймстамп)

Поддержка браузерами

Chrome, Firefox, Opera, IE7+(в 6 не тестировалась)

Буду рад отзывам, критике, найденным багам.

Ресурсы

Исходники на github тут
Скачать development версию (13kb) тут
Скачать production версию (5kb) тут


0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.