TypeScript перегрузка функций

Раздел 6.3 спецификации языка TypeScript говорит о перегрузке функций и дает конкретные примеры того, как это реализовать. Однако, если я попробую что-то вроде этого:

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, я все равно получаю ошибку компилятора. Идеи, пожалуйста.

Ответ 1

Это может быть потому, что, когда обе функции компилируются в JavaScript, их подпись полностью идентична. Поскольку у JavaScript нет типов, мы создаем две функции, принимающие одинаковое количество аргументов. Таким образом, TypeScript ограничивает нас от создания таких функций.

TypeScript поддерживает перегрузку на основе количества параметров, но шаги, которые необходимо выполнить, немного отличаются, если сравнивать с языками OO. В ответ на другой вопрос SO кто-то объяснил это с хорошим примером: Перегрузка метода?

В основном, мы делаем, мы создаем только одну функцию и количество объявлений, чтобы TypeScript не выдавал ошибок компиляции. Когда этот код скомпилирован в JavaScript, будет видна только конкретная функция. Поскольку функцию JavaScript можно вызвать, передав несколько аргументов, она просто работает.

Ответ 2

Когда вы перегружаетесь в 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 - "либо string, либо number".

Ответ 3

Вы можете объявить перегруженную функцию, объявив функцию как тип, который имеет несколько сигнатур вызова:

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

Ответ 4

Как один из руководителей других, я ободряю, что, по крайней мере, как показано в TypeScript, скомпилированном WebPack для Angular 2, вы спокойно получаете overWRITTEN вместо методов overLOADED.

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

Призвание:

myComponent.method()

похоже, выполняет метод с аргументами, молча игнорируя версию no-arg, с выходом:

with arg

Ответ 5

У меня такая же ошибка, когда я работаю с учебником TS с сайта Microsoft. Мое решение - установить расширение TSLint в VSCode.