Я работаю над файлом определения TypeScript для плагина проверки нокаута. Одна из вещей, на которой я застрял, связана с тем, как в этой библиотеке определены новые правила проверки.
Способ создания базового синхронного валидатора для ko.validation
выглядит так:
ko.validation.rules['myrulename'] = {
message: 'default message to display when validation fails',
validator: function (value, params) {
// use value and params to evaluate rule,
// then return true if valid, false if invalid
}
}
Это было бы просто, однако есть несколько другой способ создать асинхронный валидатор:
ko.validation.rules['myrulename'] = {
async: true,
message: 'default message to display when validation fails',
validator: function (value, params, callback) {
// use value and params to evaluate rule,
// then invoke callback to indicate pass / fail
// this function does not return a bool (it is void)
}
}
Асинхронный обратный вызов может принимать либо логическое значение (для проверки пройден / не пройден), либо литерал объекта (isValid
для прохождения / неудачи и message
для изменения сообщения проверки). Для этого я создал следующее:
interface KnockoutValidationAsyncCallbackArgs {
isValid: bool;
message: string;
}
interface KnockoutValidationAsyncCallback {
(result: bool): void;
(result: KnockoutValidationAsyncCallbackArgs): void;
}
Вот урезанная версия моего KnockoutValidationStatic
, которая предоставляет массив правил. Я также создал специальный интерфейс для массива правил, чтобы указать индексирование строк:
interface KnockoutValidationRulesArray extends Array {
[index: string]: KnockoutValidationRule;
}
interface KnockoutValidationStatic {
rules: KnockoutValidationRulesArray;
... other members defined on this interface
}
interface KnockoutStatic {
validation: KnockoutValidationStatic;
}
Я застрял на KnockoutValidationRule
. Я пробовал следующее:
interface KnockoutValidationRule {
async?: bool;
message: string;
validator(value: any, params: any): bool;
validator(value: any, params: any, callback: KnockoutValidationAsyncCallback): void;
}
Это отлично работает для объявлений синхронных валидаторов. Однако, когда я создаю асинхронный, я получаю следующие ошибки:
Невозможно преобразовать '{message: string; validator: (value: any, params: any, callback: KnockoutValidationAsyncCallback) => void} 'to' KnockoutValidationRule ': типы свойства' validator 'типов' {message: string; валидатор: (значение: любое, параметры: любое, обратный вызов: KnockoutValidationAsyncCallback) => void; } 'и' KnockoutValidationRule 'несовместимы:
Сигнатуры вызовов типа '(значение: любое, параметры: любое, обратный вызов: KnockoutValidationAsyncCallback) => void' и '{(значение: любое, параметры: любое): bool; (значение: любые, параметры: любые, обратный вызов: KnockoutValidationAsyncCallback): void; } несовместимы:
Сигнатура вызова требует 2 или меньше параметров
Я также рассматривал возможность сделать обратный вызов необязательным параметром, но это не работает, потому что функция возвращает разные значения в зависимости от подписи (bool без 3-го аргумента, void, если присутствует 3-й аргумент).
Что я здесь делаю не так? Что-то не так с моим строковым индексированным массивом для правил? Можно ли создать интерфейс TypeScript на основе того, как работает эта библиотека?
Обновление 1
Похоже, я был на правильном пути с перегрузками в моем KnockoutValidationRule
интерфейсе. Я только что обнаружил, что если я изменю ko.validation.rules
с KnockoutValidationRulesArray
на KnockoutValidationRule[]
, мой тестовый код будет нормально компилироваться как для синхронизирующих, так и для асинхронных валидаторов ...
interface KnockoutValidationStatic {
//rules: KnockoutValidationRulesArray; // this breaks it
rules: KnockoutValidationRule[] // this fixes it
... other members defined on this interface
}
Я неправильно объявляю массив?
Обновление 2
Вот пример кода, который я использую для проверки определений:
/// <reference path="../../ko/knockout-2.2.d.ts" />
/// <reference path="../../ko/knockout.validation.d.ts" />
module TestKoVal {
ko.validation.rules['test1'] = {
message: '',
validator: (value: any, params: any): bool => {
return false;
}
}
ko.validation.rules['test2'] = {
async: true,
message: '',
validator: function (value: any, params: any, callback: KnockoutValidationAsyncCallback): void => {
callback(false);
callback(true);
callback({ isValid: false, message: 'custom' });
}
}
}
Как я уже сказал, вышеупомянутая компилируется нормально, когда ko.validation.rules
равно KnockoutValidationRule[]
. Он не работает, когда я меняю его на KnockoutValidationRulesArray
.
KnockoutValidationAsyncCallback
заключается в том, что это не позволит коду выполнить обе перегрузки обратного вызова. В функции проверки я могу вызвать либоcallback(true)
, либоcallback({isValid: false, message: 'custom message'})
. - person danludwig   schedule 23.12.2012