TypeScript函数重载

时间:2012-11-03 19:22:24

标签: typescript overloading

TypeScript语言规范的第6.3节讨论了函数重载,并给出了如何实现它的具体示例。但是如果我尝试这样的话:

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

}

即使函数参数属于不同类型,我也会收到指示重复标识符的编译器错误。即使我在第二个createFeatureLayer函数中添加了一个额外的参数,我仍然会遇到编译器错误。想法,请。

6 个答案:

答案 0 :(得分:174)

在TypeScript中重载时,只有一个具有多个签名的实现。

class Foo {
    myMethod(a: string);
    myMethod(a: number);
    myMethod(a: number, b: string);
    myMethod(a: any, b?: string) {
        alert(a.toString());
    }
}

TypeScript只识别三个重载作为方法调用的可能签名,而不是实际的实现。

在你的情况下,我个人会使用两个名称不同的方法,因为参数中没有足够的共性,这使得方法体可能需要有很多“ifs”来决定做什么。

TypeScript 1.4

从TypeScript 1.4开始,您通常可以使用联合类型消除对重载的需要。上面的例子可以使用:

更好地表达
myMethod(a: string | number, b?: string) {
    alert(a.toString());
}

a的类型为“stringnumber”。

答案 1 :(得分:160)

这可能是因为,当两个函数都编译为JavaScript时,它们的签名完全相同。由于JavaScript没有类型,我们最终会创建两个使用相同数量参数的函数。因此,TypeScript限制我们创建这样的函数。

TypeScript支持基于参数数量的重载,但是如果我们与OO语言进行比较,则要遵循的步骤有点不同。在回答另一个SO问题时,有人用一个很好的例子解释了它:Method overloading?

基本上,我们正在做的是,我们只创建一个函数和一些声明,以便TypeScript不会产生编译错误。当此代码编译为JavaScript时,单独的具体功能将是可见的。由于可以通过传递多个参数来调用JavaScript函数,因此它可以正常工作。

答案 2 :(得分:38)

您可以通过将该函数声明为具有多个调用签名的类型来声明重载函数:

interface IFoo
{
    bar: {
        (s: string): number;
        (n: number): string;
    }
}

然后是以下内容:

var foo1: IFoo = ...;

var n: number = foo1.bar('baz');     // OK
var s: string = foo1.bar(123);       // OK
var a: number[] = foo1.bar([1,2,3]); // ERROR

函数的实际定义必须是单数的,并在其参数内部执行适当的调度。

例如,使用一个类(可以实现IFoo,但不必):

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;
    }
}

这里有趣的是any形式是隐藏更具体的类型覆盖。

var foo2: new Foo();

var n: number = foo2.bar('baz');     // OK
var s: string = foo2.bar(123);       // OK
var a: number[] = foo2.bar([1,2,3]); // ERROR

答案 3 :(得分:6)

打字稿中的函数重载:

根据Wikipedia(以及许多编程书籍),方法/函数重载的定义如下:

在某些编程语言中,函数重载或方法 重载是能够创建相同功能的多个功能 名称具有不同的实现方式。调用重载函数 将运行适合该功能的特定实现 调用的上下文,允许一个函数调用执行不同的操作 任务取决于上下文。

在打字稿中,不能有根据参数的数量和类型调用的同一函数的不同实现。这是因为将TS编译为JS时,JS中的函数具有以下特征:

  • JavaScript函数定义未为其参数指定数据类型
  • JavaScript函数在调用时不检查参数数量

因此,从严格的意义上讲,可以说不存在TS函数重载。但是,您可以在TS代码中做一些可以完美模仿函数重载的事情。

这里是一个例子:

function add(a: number, b: number, c: number): number;
function add(a: number, b: number): any;
function add(a: string, b: string): any;

function add(a: any, b: any, c?: any): any {
  if (c) {
    return a + c;
  }
  if (typeof a === 'string') {
    return `a is ${a}, b is ${b}`;
  } else {
    return a + b;
  }
}

TS文档称此方法重载,而我们基本上所做的是为TS编译器提供多个方法签名(可能的参数和类型的描述)。现在,TS可以确定在编译期间是否正确调用了函数,如果错误调用了函数,则会给我们一个错误。

答案 4 :(得分:3)

什么是函数重载?

函数重载或方法重载是使用不同的实现Wikipedia)创建具有相同名称的多个功能的功能。


什么是JS中的函数重载?

此功能在JS中是不可能的-如果有多个声明,则采用最后定义的功能:

function foo(a1, a2) { return `${a1}, ${a2}` }
function foo(a1) { return `${a1}` } // replaces above `foo` declaration
foo(42, "foo") // "42"

...以及在TS中吗?

Overloads编译时构造,对JS运行时没有影响:

function foo(s: string): string // overload #1 of foo
function foo(s: string, n: number): number // overload #2 of foo
function foo(s: string, n?: number): string | number {/* ... */} // foo implementation

如果使用上述代码(比JS安全),则会触发重复的实现错误。 TS按自上而下的顺序选择第一个配件重载,因此重载从最具体到最广泛分类。


TS中的方法重载:一个更复杂的示例

可以通过类似于函数重载的方式使用重载的类方法类型:

class LayerFactory {
    createFeatureLayer(a1: string, a2: number): string
    createFeatureLayer(a1: number, a2: boolean, a3: string): number
    createFeatureLayer(a1: string | number, a2: number | boolean, a3?: string)
        : number | string { /*... your implementation*/ }
}

const fact = new LayerFactory()
fact.createFeatureLayer("foo", 42) // string
fact.createFeatureLayer(3, true, "bar") // number

由于函数实现与所有重载签名(由编译器强制执行)兼容,因此可能存在截然不同的重载。

更多信息:

答案 5 :(得分:1)

作为对其他人的反对,我已经观察到,至少由WebPack为Angular 2编译的TypeScript表明,你悄然得到overWRITTEN而不是overLOADED方法。

myComponent {
  method(): { console.info("no args"); },
  method(arg): { console.info("with arg"); }
}

通话:

myComponent.method()

似乎用参数执行方法,默默地忽略no-arg版本,输出:

with arg