Javascript-форум (https://javascript.ru/forum/)
-   Angular.js (https://javascript.ru/forum/angular/)
-   -   Angular2+: TS выдает ошибку, если декорирую объявление метода. Но не всегда (https://javascript.ru/forum/angular/70066-angular2-ts-vydaet-oshibku-esli-dekoriruyu-obyavlenie-metoda-no-ne-vsegda.html)

Shitbox2 08.08.2017 12:04

Angular2+: TS выдает ошибку, если декорирую объявление метода. Но не всегда
 
Навешиваю на метод декоратор. В одном случае всё нормально работает:
@GET("/items")
  public getAll(): Observable<{}> { return null; };


А если не указываю тип, то получаю ошибку:
TS1249:A decorator can only decorate a method implementation, not an overload
TS2391:Function implementation is missing or not immediately following the declaration
@GET("/items")
  public getAll();


Что за дела?

Shitbox2 08.08.2017 12:12

Разобрался. Здесь { return null; } это тело функции, т.е. реализация есть.

Не понятно пока, что это за хак такой, когда пустая реализация используется. Повсеместно наблюдаю такой код

destus 08.08.2017 13:37

Цитата:

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

Shitbox2 08.08.2017 14:03

А в чем смысл? Использовать разную реализацию в зависимости от входных параметров - это понятно. Но плодить пустые функции... Шаманством попахивает. Интерфейсы и абстрактные классы для сигнатур же используются.

Пока это выглядит как обход правила, не позволяющего декорировать неимплементированные методы

destus 08.08.2017 14:22

Цитата:

А в чем смысл? Использовать разную реализацию в зависимости от входных параметров - это понятно.
иногда бывает удобно делать так. Вот например перегрузка функции get из пакета http
get(url: string, options: {
    headers?: HttpHeaders,
    observe: 'response', params?: HttpParams, reportProgress?: boolean,
    responseType: 'arraybuffer', withCredentials?: boolean,
  }): Observable<HttpResponse<ArrayBuffer>>;

get(url: string, options: {
    headers?: HttpHeaders,
    observe: 'response', params?: HttpParams, reportProgress?: boolean,
    responseType: 'blob', withCredentials?: boolean,
  }): Observable<HttpResponse<Blob>>;

get(url: string, options: {
    headers?: HttpHeaders,
    observe: 'response', params?: HttpParams, reportProgress?: boolean,
    responseType: 'text', withCredentials?: boolean,
  }): Observable<HttpResponse<string>>;

а если переписать вместе, получится каша
get(url: string, options: {
    headers?: HttpHeaders,
    observe: 'response', params?: HttpParams, reportProgress?: boolean,
    responseType: 'arraybuffer' | 'blob' | 'text', withCredentials?: boolean,
  }): Observable<HttpResponse<ArrayBuffer>> | Observable<HttpResponse<Blob>> | Observable<HttpResponse<string>>;


Цитата:

Но плодить пустые функции...
Ещё раз - функция будет одна. Всё что до реализации этой самой функции, для интерпретатора, чтобы он не ругался, когда я буду ждать тот или иной возвращаемый тип или передавать в функцию разные параметры.

Shitbox2 08.08.2017 14:56

Странно, что в реализации http это без пустых функций работает.

Т.е., когда указываю
export declare class HttpClient {
  get(...): Observable<...>;
}

это работает, а без declare
export class HttpClient {
  get(...): Observable<...>;
}

пишет TS2391:Function implementation is missing or not immediately following the declaration

Или это только для файлов деклараций справедливо .d.ts?
В самом коде Ангуляра ничего такого нет, только реализация:

get(url: string, options?: RequestOptionsArgs): Observable<Response> {
    return this.request(
        new Request(mergeOptions(this._defaultOptions, options, RequestMethod.Get, url)));
  }


Что-то я запутался совсем(

destus 08.08.2017 15:24

Shitbox2,
link
Видна подсветка красным на 9 строке? add(5, 5) подходит под сигнатуру первой функции, add('1', '2') -- второй, add(true, false) -- такого определения нет.

Shitbox2 08.08.2017 15:45

Подсветка есть. Пример понятен. Теперь вернемся к Ангуляру, к методу get из http (хороший пример)

Описанные выше сигнатуры расположены в файле client.d.ts, а сама имплементация в скомпиленных js-файлах.

В исходниках же Ангуляра имплементация в файле http.ts и декларация непонятно где
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
    return this.request(
        new Request(mergeOptions(this._defaultOptions, options, RequestMethod.Get, url)));
  }


Непонятно как это всё работает... И почему, вообще, работает

destus 08.08.2017 17:01

Shitbox2,
Компилится в js, потому что приложение на angular 2 не обязательно должно быть написано на TS. Это может быть es5, es6, Dart. То есть разработчики написали свой код на ts, скомпилили в js и создали файлы декларации (.d.ts). Зачем нужны заголовочные файлы, думаю понятно.

Shitbox2 08.08.2017 17:51

Это я ступил. Смотрел в исходниках http-сервис вместо того, чтобы открыть новый common/http-клиент. Поэтому и не сходилось ничего)


Часовой пояс GMT +3, время: 14:50.