Search
Write a publication
Pull to refresh

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

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

Что умеет


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


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


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

    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(); // []


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

    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


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


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

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";
        },
    }
]);


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

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";
    }
]);


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

// 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


Перегрузка


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

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


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

// 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


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


  • 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) тут
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.