我正在为淘汰验证插件开发一个 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)
}
}
异步回调可以采用 bool(用于验证 pass/fail)或对象文字(isValid
用于 pass/fail,message
用于更改验证消息)。为此,我创建了以下内容:
interface KnockoutValidationAsyncCallbackArgs {
isValid: bool;
message: string;
}
interface KnockoutValidationAsyncCallback {
(result: bool): void;
(result: KnockoutValidationAsyncCallbackArgs): void;
}
这是我的KnockoutValidationStatic
的精简版,它暴露了规则数组。我还为 rules 数组创建了一个特殊的接口来指定字符串索引:
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;
}
这适用于同步验证器声明。但是当我创建一个异步的时,我得到以下 error(s):
无法转换'{message:string;验证器:(值:any,params:any,callback:KnockoutValidationAsyncCallback)=> void}'to'KnockoutValidationRule':类型'{message:string;'的属性'validator'的类型验证器:(值:any,params:any,callback:KnockoutValidationAsyncCallback)=> void; }'和'KnockoutValidationRule'不兼容:
调用类型'(值:any,params:any,callback:KnockoutValidationAsyncCallback)=> void'和'{(value:any,params:any)的签名:bool; (value:any,params:any,callback:KnockoutValidationAsyncCallback):void;是不兼容的:
呼叫签名需要 2 个或更少的参数
我还考虑使回调成为可选参数,但这不起作用,因为函数根据签名返回不同的值(没有 3rd arg 的 bool,如果存在 3rd arg 则为 void)。
我在这里做错了什么?我的 string-indexed 数组的规则有问题吗?是否可以根据此库的工作方式创建 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
时失败。
2 回答
我想我可能已经弄清楚为什么以上不起作用。在 javascript 中,当您使用带有字符串的[1]数组语法作为索引器时,您不会按照通常意义创建数组。相反,该语法只是向对象添加属性。以下是功能相同的:
您可以通过修改 KnockoutValidationRule 来解决此问题:
并使用相应的更改:
这统一了两个方法签名。验证方法实际上不需要返回 bool,因此声明该方法返回 bool 的事实主要是 cosmetic/aesthetic 问题。
在codeplex 网站上讨论这个问题可能是值得的,因为我怀疑这在 JavaScript 库中是不常见的。