Definitelytyped: bluebird 3.0:グローバルPromiseのオーバーロードとして使用する方法は?

作成日 2016年08月24日  ·  44コメント  ·  ソース: DefinitelyTyped/DefinitelyTyped

こんにちは、みなさん!

グローバルPromiseオブジェクトの代わりにbluebirdを使用しています。 @lheckerによって公開されたtypedefを最新バージョンに更新しようとしましたが、問題が発生しました。グローバルPromsieは、デフォルトではオーバーロードされていません。
以前の行動をどのように達成できますか? たとえば、bluebird-global.d.tsを使用できますか?

最も参考になるコメント

こんにちは、みんな、

@types/bluebird-globalが利用可能になりました。 これらのタイピングはボンネットの下で@types/bluebird@^3.0を使用し、グローバルPromiseでbluebirdのメソッドを使用できるようにします(つまり、tsコンパイルは失敗しません)。

使い方はこちらをお読みください。

全てのコメント44件

私見では、以前のBluebirdの定義も、グローバル名前空間に大量にリークされたため、適切なソリューションではありませんでした。冗長な作業を減らすことは良い考えだと思います。

ただし、以前の定義が機能する方法は、 declare var Promise: PromiseConstructor;を定義することですが、 PromiseConstructorは以前の(グローバルに定義された)Bluebirdインターフェイスでした。

つまり、ローカルの*.d.tsファイルを作成し、このようなものを追加すると、おそらく機能する可能性がありますか?

import Bluebird = require("bluebird");
declare var Promise: Bluebird<any>;

多分うまくいくかもしれませんか?

残念だけど違う。 私はたくさんのコードを持っているので、次のように書かれています:

declare function doLoadData(): Promise<Data>

ご覧のとおり、関数はPromise<T>を返します。これは、ブルーバードではなく、標準のPromsieです。 var Promise: Bluebird<any>の宣言インターフェイスではなく、標準のPromiseコンストラクターをオーバーロードします。

このため、2.0タイピングに戻しました。

@Strateああくそー私はこれについて私がどう思うか、そして私たちが何をしようとすべきかについて長いコメントを書きました。 しかし、提出するのを忘れたようで、ついに失われました...

多くの人がこの問題を抱えているようです。

問題を示すリポジトリを作成しました: https ://github.com/d-ph/typescript-bluebird-as-global-promise

git clone && npm install && npm run tsc

問題:
サードパーティのd.tsファイルはPromiseに対して入力されます。 このPromiseは、typescriptのlib.es6.d.ts"target": "es6"の場合)または他のライブラリ、たとえばcore-js (typescriptを使用してes5にコンパイルする場合に非常に人気があります)によって定義されます。 。 最新のbluebird.d.tsは、グローバルPromiseとして宣言されていませんが、bluebird.jsはそれ自体をグローバルPromiseとして公開しています。

結果:
開発者は、サードパーティのコードから返されたPromiseでbluebirdの機能を使用できません(コンパイルは失敗します)。

期待される結果:
開発者は、サードパーティのコードから返されたPromiseでbluebirdの機能を使用できます(コンパイルは成功します)。

ブルーバードタイピングのメンテナーが誰なのかわかりません。 @lhecker 、あなたはgit blameによって返される不運な人です。 上でリンクしたgithubプロジェクトがコンパイルされるような方法でbluebirdタイピングを使用する理由として好ましい理由を教えてください。

現在のウォークアラウンド:

  1. 最も汚い。 bluebirdをインポートしたり、bluebirdタイピングを使用したりしないでください。 bluebird Promise関数の場合、次のように使用します: Promise["config"]({}); Promise.resolve("foo")["finally"](() => { console.log("lol"); })コンパイラをサイレントにします。 つまり、配列アクセス演算子を使用します: [""]
  2. 汚くて迷惑。 アプリケーションのすべてのエントリtsファイルに、次の2行を追加します。
import * as Bluebird from 'bluebird';
declare global { export interface Promise<T> extends Bluebird<T> {} }

Bluebirdの静的関数には、 Promise.config({}) Bluebird.config({})を使用します。

欠点は、IDEがこのハッキングを正しく解釈するのに苦労していることです。

うーん...皆さんが私や他の多くの人とは違う方法でBluebirdを使用しているので、皆さんがこれに問題を抱えることは私にとってちょっと予期していませんでした。 実際、私は自分でタイピングを書くことさえしませんでした! 3.0の既存のものだけをここからコピーしただけです。なぜなら、3.0のタイピングを使用する方が、何も入力しないよりも優れているからです。

問題は、TypeScriptが向かっている現在の方向は明らかにmodules > globalsであり、これは私が本当に承認していることです。 ただし、これは、モジュールがグローバルオブジェクトを変更してはならないことも意味します。特に、 Bluebirdがすべての場合にグローバルPromiseを置き換えるわけではないことを考慮する場合はそうです。 またはそのように言うと:

コード内のどこかで文字通りPromise.noConflict()を呼び出すと、「型安全性」はどうなりますか? tscですべてが正常であると通知された場合でも、グローバルPromiseタイプが元のタイプに戻り、コードがクラッシュします。

そうそう... @ d-ph。 2番目のウォークアラウンドは、モジュールシステムの精神に基づいているため、ずっと実行することを検討する必要があります。 しかし、これはライブラリにとって理想的なソリューションにすぎないことを私は知っていますが、アプリケーションにとっては本当に迷惑になる可能性があります。 私は、アプリケーションシステムが少なくともグローバルPromiseオブジェクトを確実に置き換えることができ、2.0で利用可能だったように、そのユースケースに一致する型を使用できる必要があることに同意します。

結局、TypeScriptのイデオロギーに照らして、グローバルなPromise型を拡張することは、非常に慎重に行う必要があり( noConflict()の問題などを覚えておいてください)、そうであればオプトインとしてのみ行う必要があると思います。

IMOの今後の方法は、 bluebird.d.tsファイルにあるのと同じインターフェイス宣言を使用してグローバルPromiseオブジェクトを拡張するある種のbluebird-global.d.ts (または同様の)ファイルを作成することです。 また、それらを使用する必要がある場合は、常に含めるのではなく、明示的にインポートする必要があります。 そうすれば、ほとんどのユースケースで、特にライブラリを作成するときに、アプリケーションでグローバルなPromiseを上書きするという追加の利点にアクセスしながら、安全で正しい入力を行うことができます。

このアイデアが良いアイデアだと思っていて、時間があれば、PRを作成できればいいと思います。 多くの人がそのような貢献に本当に満足していると確信しています。 🙂

私は現在、時間の不足と現時点でそのようなタイピングを必要としないために、それらのタイピングを書く立場にないので、このように言い換えています。 ご理解いただければ幸いです。

@lhecker私はあなたに同意できると思います。 Promiseをbluebirdのものにグローバルにオーバーライドする場合、typescriptコンパイラのみをハックし、現実の世界はハックしないためです。 たとえば、オーバーライドされPromiseを使用すると、typescriptはfetchがbluebirdのものを返すと見なします。

import `whatwg-fetch`;
let result = fetch("anyurl"); // this is NOT bluebird promise, but typescript think that it is.

fetchをbluebirdのPromise.resolveにラップしないと、たとえば、$# result.finallyメソッドを取得できません。

import `whatwg-fetch`;
fetch("anyurl").then().finally() // goes to runtime error with overriden global promise, but should be compile error.

したがって、使用法ごとにbluebirdを明示的にインポートする方が、より良い解決策だと思います。

import Promise from "bluebird";
import `whatwg-fetch`;
Promise.resolve(fetch("anyurl")).then().catch() // no compile error, no runtime error

コードをリファクタリングします。

回答ありがとうございます、 @ lhecker

私はあなたが言ったことすべてに同意します。 そして、サードパーティのコードをPromise.resolve()メソッドでラップする@Strateのソリューションが好きで、es6のpromiseをBluebirdに(またはBluebirdをBluebirdに変換します。実行時にBluebirdのpromiseをグローバルに保ちたいので、エラーを正しく処理するためにサードパーティのコードに依存する必要はありませんが、それは重要ではありません)。

これを正しく行う方法がわからなかったようです。 他の人が恩恵を受けると思うのは、この問題に対処する方法に関するドキュメントが増えることです。ブラウザプログラミングの世界から来た人は誰でも(nodejs / typescriptからではなく)次のようにヒットするからです。

  1. npm install <absolutely everything that uses es6 promise>
  2. npm install bluebird @types/bluebird
  3. タイプスクリプトでサードパーティのコードを使用する

また、将来の参考のために、この「サードパーティのコードがes6Promiseに対して入力された場合の使用方法」セクションをどこかに文書化しておくと便利です。 つまり、

import * as Bluebird from 'bluebird';
declare global { export interface Promise<T> extends Bluebird<T> {} }

import * as Promise from 'bluebird';
import { Observable } from "rxjs";

let observable = Promise.resolve(new Observable<number>().toPromise());

readmeまたはbluebird.d.tsファイルの上部にあるdocブロックにあります。

どう思いますか?

Promiseのグローバルオーバーライドからブルーバードのものへの移行を完了しましたが、サードパーティライブラリがブルーバードのものとして扱われていたES6Promiseを返すという問題がいくつか見つかりました。 したがって、その移動を行うと、コードベースもクリーンアップされました。 Promiseのグローバルオーバーロードから移行することをお勧めします。 乾杯 :)

私はmodules > globalsを理解していますが、議論(および/または現実)のために、私は大規模なブラウザーSPAに取り組んでおり、PromiseポリフィルとしてBluebirdを使用するタスクを課されているとしましょう。

@ d-phのコンテンツを使用して@lheckerによって提案されたbluebird-global.d.ts修正を試しています。

import * as Bluebird from 'bluebird';
declare global { export interface Promise<T> extends Bluebird<T> {} }

typings/modules/bluebird-global/index.d.ts typingsを介してインストールしました:

// Generated by typings
// Source: src/bluebird-global.d.ts
declare module 'bluebird-global' {
// via https://github.com/DefinitelyTyped/DefinitelyTyped/issues/10801
import * as Bluebird from 'bluebird';
global { export interface Promise<T> extends Bluebird<T> {} }
}

しかし、私がすべてを構築しようとすると、TypeScript(v1.8.2)は次のように文句を言います。

ERROR in /path/to/typings/modules/bluebird-global/index.d.ts
(6,27): error TS2665: Module augmentation cannot introduce new names in the top level scope.

ERROR in /path/to/src/bluebird-global.d.ts
(2,35): error TS2665: Module augmentation cannot introduce new names in the top level scope.

global-modifying-module.tsのMSの例を見てみました
https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html

そして、このエラーメッセージに関連するTSの問題
https://github.com/Microsoft/TypeScript/issues/6722

しかし、私は自分が何をすべきか途方に暮れています。 誰か助けてもらえますか?

こんにちは。

問題と解決策を示している私のリポジトリを確認していただけますか? リンク。 サードパーティからのすべての約束をbluebirdのPromiseコンストラクターにラップすることを決定するまで、私はそれに非常に満足していました。これは私が現在行っていることです。 readmeの手順を実行した後はコンパイルできませんが、コメントを解除した後は、

// declare global {
//     export interface Promise<T> extends Bluebird<T> {}
// }

コンパイルしますか?

私のリポジトリはTS2(現在は安定しています)を使用しており、1.8.2を使用しているとのことです。 TSを2にアップグレードすると、何が起こるかを確認してください。

最後に、ソリューションをグローバルd.tsファイルに配置する際に問題が発生しました。 私はそれを私のwebpackコンパイルのすべてのエントリポイントに追加することになり、問題を解決しました(これは今では理にかなっています)。 jsの設定はわかりませんが、コンパイル中に失敗するすべてのファイル(または少なくとも1つのファイル)に修正を加えて、それが役立つかどうかを確認してください。

また、BluebirdのPromise実装をグローバルPromiseとして「登録」できるようにしたいと思います。 私はこのスレッド全体を読みましたが、一部をフォローしていません。 サードパーティのライブラリがネイティブ(Bluebird以外など)のPromise実装を返すことを示唆する部分。 そのサードパーティのコードがある時点で、グローバルレベルでBluebirdの実装に置き換えられたPromiseコンストラクター( new Promise(...) )を呼び出している場合、これはどのようになりますか?

<script src="//.../bluebird.min.js"></script>
<script>
    var promise = fetch("some url");

   promise.finally(...); 
</script>

ネイティブのPromise実装を置き換えたBluebirdを含めたので、これはうまく機能しないでしょうか?

最後に、実行時にこの完全なグローバル置換を実行している場合、コンパイル時にすべてのPromiseもBluebirdに置換されるように、これについてTypeScriptに通知できるはずです。

私は何が欠けていますか?

(使用している)distバージョンのbluebirdを使用する場合、グローバルPromiseがBluebirdになっているため、サードパーティのライブラリはBluebirdを使用します。 あなたはこの部分を正しく理解します。 人々は、Bluebirdのnode.jsの使用法について話しているので、そうではないと言います。

このスレッド全体は、tsをその仮定(グローバルなPromiseはBluebirdである)でコンパイルするためのそれほど明白ではない方法に関するものです。 あなたがそれをなんとかすることができたなら(例えばdeclare global {}のものを介して)、あなたは終わりです。

@ d-phしかし、私の持ち帰りは、1回だけではなくすべての*.tsファイルでそれを行わなければならないということです-それは正しいですか? たぶん、この問題の最終的な「解決策」の要約が良いでしょう。 :)

ええ、ほら、ここには単純なjust copy&paste this line to your X file and everyone and their dog are happy nowのような解決策はありません。 または、少なくとも私はそれを認識していません。

私が最後にあなたをチェックしたとき:

  1. import * as Bluebird from 'bluebird'; declare global { export interface Promise<T> extends Bluebird<T> {} }行をすべてのエントリポイント* .tsファイルにコピーして貼り付けるか、または
  2. Bluebirdのコンストラクター関数でサードパーティのコードから返されたすべてのpromiseをラップします。 ランタイムでは(不要なランタイムオーバーヘッドを除いて)何も実行せず、コンパイル時にTSを満足させます。

繰り返しますが、解決策1では、すべてのファイルではなく、エントリポイントファイルにのみそのコードを配置する必要があります。 少なくとも、これは私のために働いたものです(webpack + awesome-typescript-loader)。

別の解決策を見つけた場合、それは文字通り開発者が1つのファイルに1行だけを入れる必要があるので、コミュニティと共有してください; p

ありがとう@ d-ph-「すべてのエントリポイント* .tsファイル」の意味を確認できますか?

うん。 「エントリポイント」の.tsファイルは.tsファイルであり、 <script>タグを介してHTMLにロードします。 つまり、これはコンパイルを開始するファイルです。

さっそくグーグルした後、私はこれを見つけました(わざわざ読んではいけません)。 つまり、bluebird.d.tsにglobal { export interface Promise<T> extends Bluebird<T> {} }を手動で追加した場合、他の場所でこれについて再度言及する必要はありません。 今はテストする時間がありませんが、作成したテストgithubリポジトリでテストしましたが、動作しているようです。

つまり、bluebird.d.tsをダウンロードして、これを変更します。

// Generated by typings
// Source: bluebird.d.ts
declare module 'bluebird' {
// Type definitions for Bluebird v3.x.x
// Project: http://bluebirdjs.com

class Bluebird<R> implements Bluebird.Thenable<R>, Bluebird.Inspection<R> {

これに:

// Generated by typings
// Source: bluebird.d.ts
declare module 'bluebird' {
// Type definitions for Bluebird v3.x.x
// Project: http://bluebirdjs.com

global { export interface Promise<T> extends Bluebird<T> {} }

class Bluebird<R> implements Bluebird.Thenable<R>, Bluebird.Inspection<R> {

明らかに、これは理想的ではありません。特に、 @types/bluebird (カスタムのハッキングされたbluebird.d.tsを使用するため、今すぐ削除する必要があります)を使用する場合は、そうです...

だから私はすでに_stubs.d.tsファイルを持っていて、それに以下を追加しました、そして私はずっと近くにいます。 Promisefinallyが存在しないという苦情はもうありませんが、何らかの理由で、 Promisedelayが存在しないというエラーが発生します。 bluebird.d.tsを編集する必要はありませんでした。 調査しますが、これは素晴らしい解決策かもしれません!

declare module "bluebird-global" {
    import * as Bluebird from "bluebird";

    global { export interface Promise<T> extends Bluebird<T> { } }
}

編集: delayに関する私の問題は、静的に呼び出していたためでした(例: Promise.delay(2000)

上記の解決策では、関数がPromise<T>を返すと、このエラーが発生します。

エラーTS2322:タイプ 'Bluebird'はタイプ' Promiseに割り当てることができません'。

これは、 PromiseBluebirdに置き換えたため、 thenなどを使用するたびに、戻り値がBluebird<T>になるためだと思います。 Promise<T>の。

これがこのハックの私の最終バージョンです。 私はこれをするのは好きではありませんが、他のオプションよりも好きです。 基本的に、インターフェイスで使用していることを繰り返して、戻り値のタイプを$#$ Bluebird $#$ではなくPromiseに変更する必要があります。 これは、それ以外のBluebird定義ファイルからの直接のコピーアンドペーストです。

_stubs.d.ts

declare module "bluebird-global" {
    import * as Bluebird from "bluebird";

    global {
        export interface Promise<T> extends Bluebird<T> {
            then<U1, U2>(onFulfill: (value: T) => U1 | Bluebird.Thenable<U1>, onReject: (error: any) => U2 | Bluebird.Thenable<U2>): Promise<U1 | U2>;
            then<U>(onFulfill: (value: T) => U | Bluebird.Thenable<U>, onReject: (error: any) => U | Bluebird.Thenable<U>): Promise<U>;
            then<U>(onFulfill: (value: T) => U | Bluebird.Thenable<U>): Promise<U>;
            then(): Promise<T>;

            finally<U>(handler: () => U | Bluebird.Thenable<U>): Promise<T>;
        }
    }
}

公式のbluebird-globalまたはbluebird-overrideの定義があると便利です。これは、既存の定義によく似ていますが、 Bluebird Promiseをどこでも使用します。

解決策を見つけることができてよかったです。

完全を期すために: @ ProTipが言ったように、 bluebird-2.0.d.ts JustWorksTMを使用します。 npm install @types/[email protected]を使用してインストールし、tsconfig.jsonのcompilerOptions.typesに追加するだけです。

{
    "compilerOptions": {
//     (...)
        "types": [
          "bluebird"
        ]
    },
    "include": [
        "src/**/*.ts"
    ]
}

その.d.tsと現在のBluebirdバージョン(つまり3.x)の違いは、手動でハッキングすることをお勧めします。

JustWorksTMとは、次のことを意味します。

a)es5ターゲット
b)es6ターゲット
c)core-jslibを使用したes5ターゲット

誰かがビルドセットアップ(webpack + awesome-typescript-loader)を使用しているかどうかに関係なく。 さらに、PhpStormIDEはまったく混乱していません。

私は今日この問題を見て時間を過ごし、実際にはMicrosoft / TypeScriptでこれらの2つのチケットを作成/更新しました: https ://github.com/Microsoft/TypeScript/issues/10178とhttps://github.com/Microsoft/TypeScript / issues / 12382 。 私の考えは、あなたが言ったように(そしてあなたの前にいくつか)、 bluebird-global.d.tsファイルが必要だということです。 コードの重複を避けるために、これでうまくいくことがわかりました。

// bluebird-global.d.ts

import * as Bluebird from "bluebird";

export as namespace Promise;
export = Bluebird;

前述の2つのチケットが解決されるか、回避策が見つかった場合。 それまでの間、ブラウザのコーディングにはbluebird-2.0.d.tsを使用することをお勧めします。

@JoshMcCullough

そのサードパーティのコードがある時点で、グローバルレベルでBliebirdの実装に置き換えられたPromiseコンストラクター(新しいPromise(...))を呼び出している場合、これはどのようになりますか?

とても簡単。 ブラウザのコンソールで試してください(Chromeを推奨):

var NativePromise = Promise;
window.Promise = function() {}; // try to overload NativePromise
NativePromise === Promise; // false. Seems it is overloaded!
// And now, let check with some native code, which return Promise, for example fetch
Object.getPrototypeOf(fetch("")) === Promise.prototype; // false, Whoops!
Object.getPrototypeOf(fetch("")) === NativePromise.prototype; // true! Double whoops!

こんにちは。 私はこれをやっていて、それはかなりスムーズです。 まず第一に、図書館プロジェクトをブルーバードに依存しないでください。 アプリケーションプロジェクトの場合、ブルーバードをインポートしますが、タイピングはインポートしません。 アプリケーションのエントリポイントで、次のようにします。

global ['Promise'] = require( 'bluebird')

これにより、アプリケーションと含まれているすべてのライブラリのグローバルPromiseオブジェクトが置き換えられます。

こんにちは、みんな、

@types/bluebird-globalが利用可能になりました。 これらのタイピングはボンネットの下で@types/bluebird@^3.0を使用し、グローバルPromiseでbluebirdのメソッドを使用できるようにします(つまり、tsコンパイルは失敗しません)。

使い方はこちらをお読みください。

素晴らしい、ありがとう@ d-ph!

@ d-ph @types/bluebird-globalをありがとう。 グローバルPromiseの代わりにbluebirdを使用するには、プロジェクトで何らかのインポートと再割り当てを行う必要がありますか?

npm install --save-dev @types/bluebird-global次に、タイピングに含まれている指示に従います:リンク(リンクは2017-04-02に更新されました)。 これだけでうまくいくはずです(つまり、手動でインポート/再割り当てする必要はありません)。

補足として、 package.json::devDependencies@types/bluebirdを記載する必要はありません。これは、自動的に暗示されるためです。

前のコメントのリンクに更新:リンク

@MichaelTontchev @ d-ph Promise.Inspectionインターフェースをbluebird-globalに追加できる可能性はありますか?

こんにちは@ksnyde。

私と話してください。 私はメンテナです。

このPromise.Inspectionを参照していることを確認してください。

そのインターフェースからのすべてのメソッドは、 bluebird-globalを介して公開されます。 つまり、以下がコンパイルされます。

let promiseInspectionTest = new Promise<void>((resolve) => {});
promiseInspectionTest.value();

したがって、これbluebird-global Promise.Inspectionとして公開するように要求しているように思われます。

これが、代わりに以下を使用することの大きな後退であるかどうかを教えてください。

import * as Bluebird from "bluebird";

class Foo<T> implements Bluebird.Inspection<T> {

}

bluebird-globalを使用しているので、明示的なdevDependenciesなしで、そのような元のbluebirdタイプをインポートすることもできます。

lib.d.tsからの標準のPromiseタイピングでこれらのタイピングを機能させるのは微妙な芸術であるため、その背後にある確固たる理由なしに、グローバルPromiseをこれ以上拡張したくありません。 bluebirdタイピングから直接このインターフェースにアクセスすることを強くお勧めします。ある日JavaScriptの達人がPromise.Inspectionを標準に追加し、 bluebird-globalタイピングを壊してしまう可能性があるためです。エンドユーザーに不必要な問題を引き起こします。

また、インターフェイスを追加したとしても、DTのメンテナは最近PRで忙しいので、インターフェイスがmasterにマージされるまで不特定の時間を待つ必要があります。

乾杯。

私は確かにあなたが議論したアプローチを当分の間使用してきました、そしてそれは適切な回避策です。 あるいは、「回避策」は間違った命名法かもしれません。

私の理解/認識は、bluebird-globalの背後にある考え方は、bluebirdが提供するPromise機能のスーパーセットを公開することでした。その場合、ユーザーとしてBluebird.InspectionPromise.Inspectionで公開されることを期待します。 ただし、Promisesの公式APIサーフェスでBluebirdを使用することだけを目的としている場合は、この「回避策」が実際には適切な長期的なソリューションであると思います。

私は自分の解釈を好みますが、必要に応じて、ここに示すソリューションを使用しても問題ありません。

私は確かにあなたがあなたの期待でどこから来ているのかわかりますが、私がbluebird-globalを作成した主な理由は、サードパーティのコードから作成されて返されたPromiseが実際にはBluebirdのpromiseのインスタンスであることをTypeScriptに知らせるためでした。他に_迷惑ではない_代替手段はありませんでしたが、グローバルPromiseシンボル上のすべてのBluebirdのインスタンスと静的メソッドを公開することでした。 前に述べたように、それが行われる方法は、単純なclass Promise<T> extends Bluebird<T> {}ではなく(元々はそうでしたが)、慎重にパッチが適用されたグローバルPromiseシンボルです。 そして、私が述べたように、私はむしろ、文字通りあなたの髪を頭から引き抜かせることがない、既知の代替案があるものを維持する必要を避けたいと思います。

これに「いいえ」と言ってすみません。 この特定の機能を要求する人がもっといる場合は、追加することを再検討します。 私はここで権威を持っているように聞こえたくありません-これはオープンソースプロジェクトであり、おそらく誰もがこの機能を押し込むことができます。それを維持するためのコストを上回らない。

乾杯。

理にかなっています。 あなたのアプローチの背後にある考え方に感謝します。

@ d-phは、次のことを意味します...「reflect」は以下のコードの関数ではないというエラーが表示されます。

image

また、エディターのインテリセンスでは、マッピング関数のプロパティpがBluebirdのPromiseであり、Bluebirdでのみ見られる拡張APIサーフェス(Promiseではない)を持っていることを正しく識別しています。

image

私はそれから頭や尾を作ることができません。 マップのイテレータ変数の_type_を調べると、次のように表示されることに気付きました。

image

これが最終的にbluebird-global定義された制限付きAPIサーフェスを取得する理由だと思いましたが、正しく解決されない理由はわかりません。

こんにちは。

再現できません:/これらのコードスニペットは私のセットアップで機能します。

初めに。 allSettled()関数でbluebird-globalを使用していません。 Bluebirdを使用して直接入力します。 これは問題ではありませんが、おそらくあなたはそれに気づいていませんでした。 次のスニペットはbluebird-globalを使用しています:

function allSettled<T>(promises: Array<Promise<T>>) {
    const reflections = Promise.all<T>(promises.map((promise => {
        return promise.reflect();
    })));

    return reflections;
}

つまり、そのスニペットはグローバルPromisebluebird-global.d.tsのBluebirdのメソッドでパッチが適用されています)にタイプします。 私が言ったように:これはあなたの情報のためのものです、あなたがそれを知らなかった場合に備えて、あなたと私のスニペットの両方が同じように機能するからです。

Bluebirdのメソッドが欠落しているという問題に戻ります。 私の推測では、実行時にグローバルPromiseをBluebirdに置き換えず、Bluebirdの代わりにグローバルPromiseを使用して構築されたPromisesでallSettled()を実行します。

私のコードといくつかのスクリーンショットをお見せしましょう。

function allSettled<T>(promises: Array<Promise<T>>) {
    const reflections = Promise.all<T>(promises.map((promise => {
        return promise.reflect();
    })));

    return reflections;
}

let promises = [
    Promise.resolve(),
    Promise.reject(new Error("rejected test")),
    new Promise<void>(() => {}),
];

let reflections = allSettled(promises);

console.log(reflections);
// this is part of my entry point

/*
 * Promise
 */
import * as Promise from 'bluebird';
import 'expose-loader?Promise!bluebird';

image
_写真1:Array.map()の約束はBluebirdです( _bitFieldのようなアンダースコアプロパティの存在によってわかります)_

image
_写真2:Promise.reflectは確かにループで定義されています_

Chrome Dev Toolsで私のようなjsブレークポイントを設定して、 .map promiseを確認してください。 さらに良いことに、コンソールにPromiseと入力して、次の出力が得られるかどうかを確認できますか。
image

次の出力が得られた場合は、実行時にグローバルPromiseをBluebirdに置き換えていません。
image

その場合、あなたはそれをする必要があります。 たとえば、エントリファイルで私のように。

最後に、開発者からのフィードバックを少しだけ紹介します。個人的には、 Array<Promise<T>> Promise<T>[]を使用します。 しかし、これはもちろん開発者の好みによるものです。 テンプレートがなく、開発者が配列アクセス演算子を使用して型を定義するCのバックグラウンドから来ました。

乾杯。

このような徹底的な説明をありがとうございました。 しかし、私が確信していなかったことの1つは、次の点が何を指しているのかということでした。

import'expose-loader?Promise!bluebird ';

@ d-phああ、上の1つのライナーは私が欠けていたものでした。 あなたの助けがなければそこにたどり着くことはなかっただろう! 私だけかもしれませんが、 READMEのテキストにExposeLoaderの使用への参照が含まれていると便利だと思います。

公平を期すために、これがwebpackの使用を必要とする場合、私はまだ100%ではありませんか? 私のターゲットはブラウザではなく、単なるノード関数です。

実際、ファイルを実行しようとすると次のエラーが発生するため、完全には機能していないように見えます(実行前にエディターにエラーはありません)。

エラー:モジュール 'expose-loader?Promise!bluebird'が見つかりません

そうです、 expose-loaderはwebpackのもの(webpackローダー)です。 したがって、webpackにそのimportステートメントを処理させないと、実行されません(つまり、「モジュールが見つかりません」というエラーが発生します)。

webpackを使用できない/使用しない場合は、実行時にグローバルPromiseをBluebirdにする別の方法を見つける必要があります。 私はノードの経験があまりありませんが、これを今見つけました:https://github.com/petkaantonov/bluebird/issues/1026(ノードのPromiseをオーバーライドします)。

最新のノード7でasync / awaitを使用する方法を見つけることをお勧めします。これが開発者に利用可能であるとき、あなたは幸運にも生きることができます。

READMEでexpose-loaderを使用することに言及することに関して:私はすでにd.tsファイルの先頭に、これは実行時にPromiseをBluebirdに置き換える開発者の仕事であると述べています: link 。 それを行う方法はたくさんあるので、実際にはそれらのどれにも言及しませんでした。 expose-loaderは、 window.Promise = Bluebirdを実行するのと同じであることに注意してください。 まあ、うまくいけば、グーグルが私の返信をインデックスに登録するので、人々はもう長い間可能なオプションを探すことはありません; p

@ d-phはネイティブのasync-awaitを楽しみにしていますが、これらの関数はすべてAWS Lambda上にあるため、今のところノード6.10.xにロックされています。 これらの関数の将来のパスでは、おそらくasync-awaitに切り替えて、TypescriptにES2015にトランスパイルさせますが、これはまだ導入したくありません。

とにかく、リンク@ d-phに感謝します、私はそのアプローチを試してみます。 ああ、そして誰かがこれらの関数の最終バージョンに興味がある場合(これはpromise-landで非常に便利です):

export function allSettled<T>(promises: Array<Promise<T>>) {
  const reflections = Promise.all<Promise.Inspection<T>>( promises.map((p => p.reflect())) );
  return reflections as Promise<Array<Promise.Inspection<T>>>;
}

export function settleProps<T>(promiseHash: IDictionary<Promise<T>>) {

  const reflections: IDictionary<Promise<Promise.Inspection<T>>> = Object.keys(promiseHash)
    .reduce((newObject: IDictionary<any>, key: string) => {
      newObject[key] = promiseHash[key].reflect();
      return newObject;
    }, {} as IDictionary<Promise<Promise.Inspection<T>>>);

  return Promise.props(reflections) as Promise<IDictionary<Promise.Inspection<T>>>;
}

完全なintelisync / type情報が利用可能であり、これは非常に優れています。

@ d-phうまくいけば、関連する質問でこれを復活させても大丈夫です...

bluebird-globalを使おうとすると、 thencatchの両方で定義の違いが少しずつ出てきているようです。 これらはbluebird-globalで特別に処理されているようですが、bluebirdを取得するのではなく、標準のPromiseAPIに制限されているようです。 例えば:

Promise.resolve(true).catch(Error, () => false)

catchは1つの引数しか期待しないため、失敗します。

そして別の問題:

Promise.resolve([3]).map((n: number) => true)

失敗する:

│TS2345: Argument of type '(n: number) => boolean' is not assignable to parameter of type 'IterateFunction<{}, boolean>'.           │
│  Types of parameters 'n' and 'item' are incompatible.                                                                             │
│    Type '{}' is not assignable to type 'number'.                                                                                  │

それらは機能する必要がありますか、それとも私は何か間違ったことをしていますか? これらは実行時に機能し、タイプチェックは行いません。

ありがとう!

こんにちは、

.catch(Error, function)については、$ .then.catch (およびそれ以上)は他のBluebird関数とは異なる方法で処理されると言って間違いありません。 ただし、特定の.catch(Error, function)オーバーライドはbluebird-globalに含まれています。 私は再確認し、コンパイルすることができます:

Promise.resolve(true).catch(Error, () => false)

TS3.0.1と2.9.2で確認しました。 ここで問題が発生する理由がわかりません。 bluebird-globalの後にグローバルPromiseをオーバーライドするTSプロジェクトに固有の何かがあるかもしれません。 わからない。 おそらく、非常に基本的なTSプロジェクトから始めて、現在のプロジェクトからさらに依存関係を追加することによって、問題の原因を絞り込み、どの時点で問題が発生するかを確認してください。

他の問題について:なぜそれが機能しないのかわかりません。 そして、はい、それは動作するはずです。 githubの問題を作成してください。そこから始めます。 問題に関するいくつかの事実は次のとおりです。

  1. bluebird-global.map()で行うことはすべて、$ bluebird.d.ts.map()型定義を再利用することです。 言い換えれば、欠陥はbluebird-globalタイピングに起因するものであってはなりません。
  2. あなたが言及した行はPromise.map()で失敗しますが、 Bluebird.map()で機能します:
import Bluebird = require('bluebird');

Bluebird.resolve([3]).map((n: number) => true); // works

Promise.resolve([3]).map((n: number) => true); // fails
  1. タイプスクリプトの問題を解読するためにしばらく時間を費やした後(基本的に:TSがn {}であると結論付ける理由)、 bluebird.d.tsも機能しないはずだと結論付けました。しかし、それは私にはわからない理由で機能します。 簡単に言うと、抽象化レイヤーをすべて削除した後、 .map()が入力されるのは次のとおりです。
map<U>(
    mapper: (
        item: U,
        index: number,
        arrayLength: number
    ) => U | PromiseLike<U>,
    options?: Bluebird.ConcurrencyOption
): Bluebird<T extends Iterable<any> ? U[] : never>;

mapper関数の戻り型は、$ itemの型と同じ(または同じPromise)である必要があることを示しています。 この例では、アイテムのタイプはnumberで、返品タイプはbooleanです。 Bluebirdを直接使用すると、なぜこれがコンパイルされるのか理解できませんが、グローバルPromiseを使用するとコンパイルされません。 ちなみに、あなたの例のリターンタイプを任意の数に変更すると、それでも機能しません。 ただし、 itemany型である可能性があると言うと、機能します。 bluebird.d.tstype IterableItem<R>と、このコンテキストでの使用法に問題があります。

@ d-ph


編集:

map()の「非レイヤー化」フォームをもう一度確認しましたが、 mapper関数は、 itemのタイプと同じ戻りタイプを持つようにタイプされていません(私はそれを考えましただった)。 私の悪い。

bluebird-globalが.map()で行うことはすべて、bluebird.d.tsの.map()型定義を再利用するだけです。

ジェネリッククラスBluebird<R>から型をコピーすると、親から推測できないため、デフォルトでR{}になるという問題はありますか?

map: typeof Bluebird<T>.prototype.mapが機能するのだろうか? (私はまだこれを試していません)

重要:
@types/bluebird-globalを使用している場合は、@ d-phが言うように、依存関係@types/bluebirdを削除します

npm install --save-dev @types/bluebird-global次に、タイピングに含まれている指示に従います:リンク(リンクは2017-04-02に更新されました)。 これだけでうまくいくはずです(つまり、手動でインポート/再割り当てする必要はありません)。

補足として、 package.json::devDependencies@types/bluebirdを記載する必要はありません。これは、自動的に暗示されるためです。

両方があると、 @types/bluebirdと私のグローバルPromise( @types/bluebird-global )によって返されるタイプ間の不一致が発生していました。

このページは役に立ちましたか?
0 / 5 - 0 評価