首页 文章

如何使用 string-indexed 数组为重载函数创建 TypeScript 接口定义?

提问于
浏览
2

我正在为淘汰验证插件开发一个 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.rulesKnockoutValidationRulesArray更改为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.rulesKnockoutValidationRule[]时,上面的编译很好。当我将其更改为KnockoutValidationRulesArray时失败。

2 回答

  • 0

    我想我可能已经弄清楚为什么以上不起作用。在 javascript 中,当您使用带有字符串的[1]数组语法作为索引器时,您不会按照通常意义创建数组。相反,该语法只是向对象添加属性。以下是功能相同的:

    ko.validation['test1'] = { ... };
    ko.validation.test1 = { ... };
    
  • 0

    您可以通过修改 KnockoutValidationRule 来解决此问题:

    export interface KnockoutValidationRule {
        async?: bool;
        message: string;
        validator: (value: any, params: any, callback?: KnockoutValidationAsyncCallback): bool;
    }
    

    并使用相应的更改:

    ko.validation.rules['test2'] = {
        async: true,
        message: '',
        validator: (value: any, params: any, callback?: KnockoutValidationAsyncCallback): bool => {
            callback(false);
            callback(true);
            callback({ isValid: false, message: 'custom' });
        }
    }
    

    这统一了两个方法签名。验证方法实际上不需要返回 bool,因此声明该方法返回 bool 的事实主要是 cosmetic/aesthetic 问题。

    codeplex 网站上讨论这个问题可能是值得的,因为我怀疑这在 JavaScript 库中是不常见的。

相关问题