TypeScript方法重写规则

11 浏览
0 Comments

TypeScript方法重写规则

TypeScript语言规范的第6.3节讨论了函数重载,并且给出了具体的实现示例。但是,如果我尝试像下面这样的写法:\n

export class LayerFactory { 
    constructor (public styleFactory: Symbology.StyleFactory) { }
    createFeatureLayer (userContext : Model.UserContext, mapWrapperObj : MapWrapperBase) : any {           
         throw "not implemented";
    }                 
    createFeatureLayer(layerName : string, style : any) : any {
        throw "not implemented";
     }        
}

\n我会得到一个编译器错误,指示有重复的标识符,即使函数参数的类型是不同的。即使我给第二个createFeatureLayer函数添加一个额外的参数,我仍然会得到编译器错误。请提供建议。

0
0 Comments

TypeScript中的方法重写规则

在TypeScript中,可以通过声明函数具有多个调用签名的类型来声明重载函数。然后,实际的函数定义必须是单一的,并在其参数上进行适当的分派。

例如,可以使用一个类来定义重载函数:

class Foo {
    public bar(s: string): number;
    public bar(n: number): string;
    public bar(arg: any): any {
        if (typeof(arg) === 'number')
            return arg.toString();
        if (typeof(arg) === 'string')
            return arg.length;
    }
}

上述示例中的`bar`方法具有两个重载签名,一个接受字符串参数并返回数字,另一个接受数字参数并返回字符串。在函数的实际定义中,通过检查参数的类型来决定返回值。

值得注意的是,更具体类型的重载会“隐藏”通用的`any`形式的重载。这意味着如果调用重载函数时,存在一个与更具体重载匹配的签名,则会选择更具体的重载。

以下是一个使用重载函数的示例:

var foo: Foo = new Foo();
var n: number = foo.bar('baz');     // 返回字符串的长度,类型为number,OK
var s: string = foo.bar(123);       // 将数字转换为字符串,类型为string,OK
var a: number[] = foo.bar([1,2,3]); // 参数类型不匹配,报错

在此示例中,`foo`是`Foo`类的实例,通过调用`bar`方法,可以根据传入的参数类型进行正确的分派。如果传入的参数类型与重载签名不匹配,则会报错。

TypeScript中的方法重写规则允许声明函数具有多个调用签名,通过检查参数类型来决定返回值。通过使用类或接口来定义重载函数,可以实现方法的重写。当调用重载函数时,会根据传入参数的类型选择适当的重载签名,并进行相应的分派。如果参数类型与重载签名不匹配,则会报错。

0
0 Comments

TypeScript中的方法重载规则

在TypeScript中,方法重载是基于参数数量进行的,但与面向对象语言相比,需要遵循一些不同的步骤。当我们将这些函数编译成JavaScript时,它们的签名完全相同。由于JavaScript没有类型,我们最终创建了两个参数数量相同的函数。因此,TypeScript限制我们创建这样的函数。

解决方法是创建一个函数和多个声明,以便TypeScript不会给出编译错误。当将此代码编译为JavaScript时,只有具体的函数才会可见。由于JavaScript函数可以通过传递多个参数来调用,所以它可以正常工作。

可以通过修改语言来支持这一点。理论上,可以生成具有不同名称的函数实现,并由编译的TypeScript调用(例如,createFeatureLayer_1和createFeatureLayer_2),然后createFeatureLayer可以根据参数的内容确定调用哪一个,以便与原始JavaScript进行互操作。

TypeScript的重载不仅可以基于参数数量进行,还可以基于类型进行,如Steve Fenton的答案所示。

TypeScript应该真正生成选择唯一命名的实现的"元函数",并根据传递的参数内容进行调用。现在存在一个问题,你可以通过编译器,但是你对类型嗅探的实现可能是不正确的。

如果有一种可靠的方法在运行时检查类型,TypeScript会这样做。

这更加复杂,使用JavaScript的类型是可行的,但是在运行时丢失了TS特定的概念,如接口、类型、枚举、泛型等。这也是为什么无法使用someObject instanceof ISomeInterfaceDefinedInTypeScript的原因。

根据Matthijs Wessels的评论-这个答案是误导性的,应该认为Steve Fenton的答案是正确的。在TypeScript中,重载的函数/方法始终共享一个处理类型缩小(即确定调用了哪个重载)的实现。尽管TypeScript的重载仍然有用,因为它基于重载签名而不是更一般的实现签名对函数使用进行类型检查。

不要小气,JavaScript确实有类型,只是在编译时不知道。但是TypeScript在编译时知道类型,所以可以在编译时解决这个问题。如果存在歧义,要么编译失败,要么让用户提供默认实现。这个功能似乎不难添加。

0
0 Comments

TypeScript方法重载规则的出现原因是为了在方法调用时识别可能的签名,而不是实际的实现。此规则要求实现的签名必须与所有重载兼容。解决方法可以是使用不同名称的两个方法,以避免在方法体中使用大量的"ifs"来决定要执行的操作。

另一种解决方法是使用工厂方法来创建对象,例如通过调用`Foo.fromObject(obj)`和`Foo.fromJson(str)`来创建对象,而不需要进行分支判断。

然而,如果想要将参数分别传递,这种方法可能不太适用。在这种情况下,使用联合类型可能会有问题,特别是如果需要根据参数的不同返回不同的类型。对于这种情况,重载是最好的解决方法。

需要注意的是,即使实现的方法是`method(a: string, b?: string) {...}`,在调用时仍然需要定义`method(a: string, b: string);`。

TypeScript方法重载规则的出现是为了在方法调用时识别可能的签名,并提供了解决方法,可以使用不同名称的方法或使用重载来解决参数和返回类型的问题。

0