Определение типа TypeScript для promise.prototype.finally


person jpierson    schedule 08.03.2016    source источник


Ответы (3)


Хотя ответ от Славы правильный, он касается только набора блока finally. Чтобы на самом деле включить оболочку в ваш код, чтобы вы могли написать p.finally(() => { ... }), вам нужно вызвать оболочку.

К сожалению, типы на DefinitelyTyped в настоящее время не поддерживают shim поэтому, пока это не поддерживается, я бы посоветовал добавить типизацию самостоятельно.

<удар>

declare interface Promise<T> {
  finally<U>(onFinally?: () => U | Promise<U>): Promise<U>;
}

declare module 'promise.prototype.finally' {
  export function shim(): void;
}

Типы теперь доступны. Установить с помощью

npm install --save-dev @types/promise.prototype.finally

В вашем коде TypeScript во время начальной загрузки приложения вы можете вызвать

import { shim } from 'promise.prototype.finally';
shim();

Это добавит блок finally к прототипу Promise, что позволит вам использовать finally по мере необходимости.

person Tom Spencer    schedule 14.12.2016
comment
Хм, я не могу заставить это работать с Visual Studio Code 1.20 - он будет построен, но при запуске кода я получу ошибку «Не удается найти модуль 'promise.prototype.finally', хотя модуль доступен в node_modules@types. Интересно, стоит ли это вообще исследовать, поскольку github.com/Microsoft/TypeScript/issues/20411 добавлена ​​встроенная поддержка для наконец, наконец. - person omni; 12.02.2018
comment
Просто использование yarn add @types/promise.prototype.finally --dev помогло мне - person zed; 17.07.2018

Для тех, кто интересуется, как заставить это работать изначально без каких-либо прокладок: начиная с TS 2.7 это возможно.

Обратите внимание, что TS 2.7 еще не полностью (26 февраля 2018 г.) совместим с ES2018. Несмотря на то, что все еще есть несколько вещей, отсутствует, Promise.наконец-то попал в версию 2.7. Также tsconfig-schema уже должна принимать ES2018 в качестве цели, но пока TS 2.7 не знает ES2018. На данный момент, чтобы использовать новые функции, такие как Promise.finally, которые уже есть в версии 2.7, вам придется использовать "target": "ESNEXT" в файле tsconfig.json.

Тогда вы сможете написать такой код:

myAsyncFunction().then
(
  (var) => console.log("executing then. " + var)
)
.catch
(
  (var) => console.log("executing catch. " + var)
)
.finally
(
  () => console.log("executing finally.")
)

Обратите внимание, что finally не принимает никаких аргументов в силу своей природы.

ВАЖНО: хотя TS будет правильно транспилировать и понимать, что вы делаете, вам все равно нужно проверить, поддерживает ли ваш JS-движок Promise.finally. В моем случае я использовал NodeJs 8.x, и, конечно же, созданный JS не был исполняемым, потому что Promise.Finally поддерживается, начиная с , в последних ночных сборках NodeJs 10.x Node 10.x (стабильная), см. эту ссылку.

person omni    schedule 26.02.2018

Вы можете написать свой собственный файл d.ts и указать ссылку на него в файле tsconfig.json. Если вы это сделаете, вы можете внести свой вклад в git DefinitelyTyped для других, таких как вы.

Обновлять:

Если я правильно понял, что вы имеете в виду, вы можете расширить существующий класс Promise в своем собственном файле d.ts. Сделайте метод необязательным, чтобы он не сообщал вам, что фактический класс Promise неправильно реализует интерфейс. Вам нужно расширить его как интерфейс.

Ваш файл d.ts должен выглядеть так

declare module 'es6-promise/dist/es6-promise' {
    export interface Promise <R> {
      finally?<U>(onFinally?: () => U | Promise<U>): Promise<U>;
    }
}

И он должен работать корректно...

В качестве примера я создал для вас проект: promise-extension-typescript-example

Я создал запрос на включение в git-репозиторий DefinitelyTyped, надеюсь, он будет принят, и вы сможете скачать его оттуда...

person Slava Shpitalny    schedule 08.03.2016
comment
Я точно знаю об этих моментах. Ситуация, которую я описал выше, специфична для этого пакета, где он изменяет существующий объект/класс вместо определения нового типа или набора типов. - person jpierson; 08.03.2016
comment
Я не уверен насчет Thenable, но я работаю с промисами, как определено в полифилле ES6 es6-promise, но предполагается, что promise.prototype.finally поддерживает любую реализацию промисов, совместимую с ES5. Тип, с которым я работаю, это Promise‹any›. Замена Thenable на Promise в вашей реализации выше у меня не работает, потому что tsc выдает ошибку на сайте импорта для полифилла Promise import { Promise } from 'es6-promise';. - person jpierson; 08.03.2016
comment
Если вы посмотрите в файле d.ts es6 -promise вы увидите, что Promise реализует Thenable. В коде, который я вам дал, я расширяю этот интерфейс новым методом - person Slava Shpitalny; 08.03.2016
comment
Из того, что я вижу, как описано выше, расширение интерфейса путем написания нового интерфейса с тем же именем не совместимо с компилятором TypeScript. - person jpierson; 09.03.2016
comment
Вы можете увидеть, как это работает, здесь: Площадка для машинописи - person Slava Shpitalny; 09.03.2016
comment
Кажется, там работает, но я получаю сообщение об ошибке. Объявление импорта конфликтует с локальным объявлением интерфейса «Thenable» Thenable‹T› путем импорта через import { Promise, Thenable } from 'es6-promise';, за которым следует блок кода, который вы разместили выше. Возможно, таким образом можно изменить только интерфейсы в области локального модуля? - person jpierson; 09.03.2016
comment
Вы определили интерфейс в другом файле d.ts и добавили его в tsconfig.json или просто добавили в файл ts? - person Slava Shpitalny; 09.03.2016
comment
Я добавил еще один файл d.ts, и он работал слишком хорошо, выдавало ошибку, что Promise неправильно реализует интерфейс, я посмотрю на это - person Slava Shpitalny; 09.03.2016
comment
Я обновил ответ, сделав метод необязательным и поместив интерфейс внутри модуля. - person Slava Shpitalny; 09.03.2016
comment
Давайте продолжим обсуждение в чате. - person jpierson; 09.03.2016
comment
Я думаю, что мой отредактированный ответ должен ответить на ваш вопрос сейчас - person Slava Shpitalny; 09.03.2016