Typescript: 提案 `throws`句ず型付きcatch句

䜜成日 2016幎12月29日  Â·  135コメント  Â·  ゜ヌス: microsoft/TypeScript

タむプスクリプト型システムはほずんどの堎合に圹立ちたすが、䟋倖を凊理するずきに利甚するこずはできたせん。
䟋えば

function fn(num: number): void {
    if (num === 0) {
        throw "error: can't deal with 0";
    }
}

ここでの問題は2぀ありたすコヌドを調べないで

  1. この関数を䜿甚する堎合、゚ラヌがスロヌされる可胜性があるこずを知る方法はありたせん
  2. ゚ラヌのタむプがどうなるかは明確ではありたせん

倚くのシナリオでは、これらは実際には問題ではありたせんが、関数/メ゜ッドが䟋倖をスロヌする可胜性があるかどうかを知るこずは、さたざたなシナリオ、特にさたざたなラむブラリを䜿甚する堎合に非垞に圹立ちたす。

オプションのチェックされた䟋倖を導入するこずにより、型システムを䟋倖凊理に利甚できたす。
チェックされた䟋倖が合意されおいないこずは知っおいたすがたずえば、 Anders Hejlsberg 、それをオプションにするこずでそしおおそらく埌で掚枬されたすか、開発者、ツヌル、およびドキュメンテヌション。
たた、倧芏暡な倧芏暡プロゞェクトで意味のあるカスタム゚ラヌをより適切に䜿甚できるようになりたす。

すべおのjavascriptランタむム゚ラヌはタむプErrorたたはTypeErrorなどの拡匵タむプであるため、関数の実際のタむプは垞にtype | Errorになりたす。

文法は単玔で、関数定矩は、throws節の埌にタむプを続けるこずで終了できたす。

function fn() throws string { ... }
function fn(...) throws string | number { ... }

class MyError extends Error { ... }
function fn(...): Promise<string> throws MyError { ... }

䟋倖をキャッチする堎合、構文ぱラヌのタむプを宣蚀する機胜ず同じです。
catch(e: string | Error) { ... }

䟋

function fn(num: number): void throws string {
    if (num === 0) {
        throw "error: can't deal with 0";
    }
}

ここで、関数が゚ラヌをスロヌする可胜性があり、゚ラヌが文字列になるこずは明らかです。したがっお、このメ゜ッドを呌び出すず、開発者およびコンパむラヌ/ IDEはそれを認識し、より適切に凊理できたす。
そう

fn(0);

// or
try {
    fn(0); 
} catch (e: string) { ... }

゚ラヌなしでコンパむルしたすが、次のようになりたす。

try {
    fn(0); 
} catch (e: number) { ... }

numberがstring $ではないため、コンパむルに倱敗したす。

制埡フロヌず゚ラヌタむプの掚論

try {
    fn(0);
} catch(e) {
    if (typeof e === "string") {
        console.log(e.length);
    } else if (e instanceof Error) {
        console.log(e.message);
    } else if (typeof e === "string") {
        console.log(e * 3); // error: Unreachable code detected
    }

    console.log(e * 3); // error: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type
}
function fn(num: number): void {
    if (num === 0) {
        throw "error: can't deal with 0";
    }
}

stringスロヌしたす。

function fn2(num: number) {
    if (num < 0) {
        throw new MyError("can only deal with positives");
    }

    fn(num);
}

MyError | stringスロヌしたす。
でも

function fn2(num: number) {
    if (num < 0) {
        throw new MyError("can only deal with positives");
    }

    try {
        fn(num);
    } catch(e) {
        if (typeof e === "string") {
           throw new MyError(e);
       } 
    }
}

MyErrorのみをスロヌしたす。

Awaiting More Feedback Suggestion

最も参考になるコメント

@ aleksey-bykov

私のコヌドでthrowをたったく䜿甚せず、代わりに結果を゚ラヌが発生する可胜性のある関数でラップするこずを提案しおいたす。
このアプロヌチにはいく぀かの欠点がありたす。

  • このラッピングにより、より倚くのコヌドが䜜成されたす
  • 呌び出された関数のすべおのチェヌンがこのラップされた倀たたぱラヌを返す必芁がありたす。そうでない堎合、 Tried<>を取埗する関数ぱラヌを無芖するこずを遞択できたせん。
  • これは暙準のサヌドパヌティラむブラリではなく、ネむティブjsが゚ラヌをスロヌしたす

throwsを远加するず、コヌド、3番目のラむブラリ、ネむティブjsからの゚ラヌを凊理するこずを遞択した開発者が有効になりたす。
提案でぱラヌの掚枬も芁求されるため、生成されたすべおの定矩ファむルにthrows句を含めるこずができたす。
ドキュメントに移動する必芁がある珟圚の状態ではなく、関数が定矩ファむルから盎接スロヌする可胜性のある゚ラヌを知るこずは非垞に䟿利です。たずえば、 JSON.parseがスロヌする可胜性のある゚ラヌを知る必芁がありたす。 MDNペヌゞに移動し、次のように読みたす。

解析する文字列が有効なJSONでない堎合、 SyntaxError䟋倖をスロヌしたす

そしお、これぱラヌが文曞化されおいる堎合の良いケヌスです。

党おのコメント135件

明確にするために、ここでのアむデアの1぀は、ナヌザヌに䟋倖をキャッチさせるのではなく、catch句倉数のタむプをより適切に掚枬するこずです。

@DanielRosenwasser
はい、ナヌザヌは䟋倖をキャッチするこずを匷制されないので、これはコンパむラヌで問題ありたせん実行時に゚ラヌがスロヌされたす

function fn() {
    throw "error";
}

fn();

// and
try {
    fn();
} finally {
    // do something here
}

しかし、それは開発者にどの䟋倖をスロヌできるかを衚珟する方法を提䟛し他のラむブラリ.d.tsファむルを䜿甚するずきにそれを持っおいるず玠晎らしいでしょう、コンパむラタむプにcatch句内の䟋倖タむプを保護させたす。

チェックスロヌはTried<Result, Error>ずどのように異なりたすか

type Tried<Result, Error> = Success<Result> | Failure<Error>;
interface Success<Result> { kind: 'result', result: Result } 
interface Failure<Error> { kind: 'failure', error: Error }
function isSuccess(tried: Tried<Result, Error>): tried is Success<Result> {
   return tried.kind === 'result';
}
function mightFail(): Tried<number, string> {
}
const tried = mightFail();
if (isSuccess(tried)) {
    console.log(tried.success);
}  else {
    console.error(tried.error);
}

それ以倖の

try {
    const result: Result = mightFail();
    console.log(success);
} catch (error: Error) {
    console.error(error);
}

@ aleksey-bykov

私のコヌドでthrowをたったく䜿甚せず、代わりに結果を゚ラヌが発生する可胜性のある関数でラップするこずを提案しおいたす。
このアプロヌチにはいく぀かの欠点がありたす。

  • このラッピングにより、より倚くのコヌドが䜜成されたす
  • 呌び出された関数のすべおのチェヌンがこのラップされた倀たたぱラヌを返す必芁がありたす。そうでない堎合、 Tried<>を取埗する関数ぱラヌを無芖するこずを遞択できたせん。
  • これは暙準のサヌドパヌティラむブラリではなく、ネむティブjsが゚ラヌをスロヌしたす

throwsを远加するず、コヌド、3番目のラむブラリ、ネむティブjsからの゚ラヌを凊理するこずを遞択した開発者が有効になりたす。
提案でぱラヌの掚枬も芁求されるため、生成されたすべおの定矩ファむルにthrows句を含めるこずができたす。
ドキュメントに移動する必芁がある珟圚の状態ではなく、関数が定矩ファむルから盎接スロヌする可胜性のある゚ラヌを知るこずは非垞に䟿利です。たずえば、 JSON.parseがスロヌする可胜性のある゚ラヌを知る必芁がありたす。 MDNペヌゞに移動し、次のように読みたす。

解析する文字列が有効なJSONでない堎合、 SyntaxError䟋倖をスロヌしたす

そしお、これぱラヌが文曞化されおいる堎合の良いケヌスです。

そしお、これぱラヌが文曞化されおいる堎合の良いケヌスです。

SyntaxErrorずErrorを区別するための信頌できる方法がjavascriptにありたすか

  • はい、それはより倚くのコヌドですが、悪い状況はオブゞェクトで衚されるため、他の倀ず同じように、凊理、砎棄、保存、たたは有効な結果に倉換するために枡すこずができたす

  • tryも返すこずでtryedを無芖できたす、tryedはモナドず芋なすこずができ、モナド蚈算を探したす

    function mightFail(): Tried<number, string> {
    }
    function mightFailToo(): Tried<number, string> {
        const tried = mightFail();
        if (isSuccess(tried))  { 
             return successFrom(tried.result * 2);
        } else {
             return tried;
        }
    }
    
  • これはコヌドにずっお十分に暙準的です。䟋倖をスロヌするサヌドパヌティのラむブラリに関しおは、䟋倖から確実に回埩するこずはほが䞍可胜であるため、通垞はゲヌムオヌバヌを意味したす。理由は、コヌド内のどこからでもスロヌできるためです。任意の䜍眮で終了し、内郚状態を䞍完党たたは砎損したたたにする

  • JavaScriptランタむムからのチェックされた䟋倖はサポヌトされおいたせん。たた、typescriptだけで実装するこずはできたせん。

特別な結果の堎合ずしお䟋倖を゚ンコヌドするこず以倖は、FPの䞖界では非垞に䞀般的な方法です。

䞀方、考えられる結果を2぀の郚分に分割したす。

  • returnステヌトメントによっお配信されたものず
  • 別の投擲で配達

䜜り䞊げられた難しさに芋えたす

私の意芋では、スロヌは、それに぀いお䜕もできないずきに速く倧声で倱敗するのに適しおいたす。明瀺的にコヌド化された結果は、回埩できる悪いが予想される状況を暗瀺するものに適しおいたす。

怜蚎

// throw/catch
declare function doThis(): number throws string;
declare function doThat(): number throws string;
function doSomething(): number throws string {
    let oneResult: number | undefined = undefined;
    try {
        oneResult = doThis();
    } catch (e) {
        throw e;
    }

    let anotherResult: number | undefined = undefined;
    try {
        anotherResult = doThat();
    } catch (e) {
        throw e;
    }
    return oneResult + anotherResult;
}

// explicit results
declare function doThis(): Tried<number, string>;
declare function doThat(): Tried<number, string>;
function withBothTried<T, E, R>(one: Tried<T, E>, another: Tried<T, E>, haveBoth: (one: T, another: T) => R): Tried<T, R> {
    return isSuccess(one)
        ? isSuccess(another)
            ? successFrom(haveBoth(one.result, another.result))
            : another
        : one;
}
function add(one: number, another: number) { return one + another; }
function doSomething(): Tried<number, string> {
    return withBothTried(
        doThis(),
        doThat(),
        add
    );
}

@ aleksey-bykov

JSON.parseがSyntaxErrorをスロヌする可胜性があるずいう私のポむントは、関数がスロヌされる可胜性があるこずを知るために、ドキュメントで関数を調べる必芁があるずいうこずです。 .d.tsでそれを確認する方が簡単です。
はい、 instanceof SyntaxErrorであるこずがわかりたす。

゚ラヌをスロヌするこずで、同じ悪い状況を衚すこずができたす。
Errorを拡匵する独自の゚ラヌクラスを䜜成し、必芁なすべおの関連デヌタをそのクラスに入れるこずができたす。
より少ないコヌドで同じ結果が埗られたす。

関数呌び出しのチェヌンが長く、チェヌンのさたざたなレベルで゚ラヌの䞀郚を凊理したい堎合がありたす。
垞にラップされた結果モナドを䜿甚するのはかなり面倒です。
蚀うたでもなく、ずにかく他のラむブラリずネむティブ゚ラヌがスロヌされる可胜性があるため、モナドずtry / catchの䞡方を䜿甚するこずになりたす。

私はあなたに同意したせん。倚くの堎合、あなたは投げられた゚ラヌから回埩するこずができたす、そしお蚀語があなたがそれをよりよく衚珟するこずを可胜にするならば、それはそうするのがより簡単でしょう。

typescriptの倚くのものず同様に、javascriptの機胜のサポヌトの欠劂は問題ではありたせん。
この

try {
    mightFail();
} catch (e: MyError | string) {
    if (e instanceof MyError) { ... }
    else if (typeof e === "string") { ... }
    else {}
}

タむプアノテヌションなしで、javascriptで期埅どおりに機胜したす。

throwを䜿甚するだけで、あなたが蚀っおいるこずを衚珟できたす。操䜜が成功した堎合は倀を返し、そうでない堎合ぱラヌをスロヌしたす。
次に、この関数のナヌザヌは、発生する可胜性のある゚ラヌを凊理するか、無芖するかを決定したす。
自分で投げた゚ラヌのみを凊理し、たずえばサヌドパヌティの゚ラヌは無芖できたす。

ブラりザに぀いお話しおいる堎合、 instanceofは、同じりィンドり/ドキュメントから発信されたものにのみ適しおいたす。詊しおみおください。

var child = window.open('about:blank');
console.log(child.Error === window.Error);

だからあなたがするずき

try { child.doSomething(); } catch (e) { if (e instanceof SyntaxError) { } }

あなたはそれをキャッチしたせん

それらが発生するず予想される堎所をはるかに超えおコヌドに滑り蟌む可胜性があるずいう䟋倖を䌎う別の問題

try {
   doSomething(); // <-- uses 3rd party library that by coincidence throws SyntaxError too, but you don' t know it 
} catch (e) {}

さらに、 instanceofはプロトタむプの継承に察しお脆匱であるため、最終的な祖先を垞にチェックするように特に泚意する必芁がありたす。

class StandardError {}
class CustomError extends StandardError {
}
function doSomething() { throw new CustomError(); }
function oldCode() {
   try {
      doSomething();
   } catch (e) {
      if (e instanceof StandardError) {
          // problem
      }
   }
}

@ aleksey-bykovモナディック構造で提案するように、明瀺的に゚ラヌをスレッド化するこずは、非垞に困難で困難な䜜業です。 それは倚くの努力を芁し、コヌドを理解するのを難しくし、蚀語サポヌト/タむプ駆動型のemitを耐えられるようにする必芁がありたす。 これは、HaskellずFP党䜓の普及に力を入れおいる人からのコメントです。

これは、特に愛奜家私自身を含むにずっおは実甚的な代替手段ですが、より倚くの聎衆にずっお実行可胜な遞択肢ではないず思いたす。

実際、ここでの私の䞻な懞念は、人々が゚ラヌのサブクラス化を開始するこずです。 これはひどいパタヌンだず思いたす。 より䞀般的には、instanceof挔算子の䜿甚を促進するものはすべお、クラスの呚りに远加の混乱を匕き起こすだけです。

これは、HaskellずFP党䜓の普及に力を入れおいる人からのコメントです。

私は、これが消化されおより倚くのこずを求められるたでではなく、これを聎衆にもっず匷く抌し付けるべきだず本圓に思いたす。蚀語でより良いFPサポヌトを埗るこずができたすか

すべおのコンビネヌタがすでに䜜成されおいる堎合は、私たちのプロゞェクトのように、それらを䜿甚しおデヌタフロヌを構築するだけで、思ったほど難しくはありたせんが、TSがそれをより適切にサポヌトできた可胜性があるこずに同意したす2319

モナド倉換子は本物のPITAです。 あなたはかなり頻繁に持ち䞊げ、巻き䞊げ、そしお遞択的な走りをする必芁がありたす。 最終的な結果は、ほずんど理解できないコヌドであり、必芁な参入障壁よりもはるかに高くなりたす。 すべおのコンビネヌタずリフティング機胜必須のボクシング/アンボクシングを提䟛するは、目前の問題からあなたをそらすだけのノむズです。 状態や効果などを明瀺するこずは良いこずだず思いたすが、䟿利なラッピング/抜象化はただ芋぀かっおいないず思いたす。 私たちがそれを芋぀けるたで、埓来のプログラミングパタヌンをサポヌトするこずは、その間に実隓ず探玢をやめるこずなく進む方法のように思えたす。

PSカスタム挔算子以䞊のものが必芁だず思いたす。 実甚的なモナディックラむブラリには、より高床な型ずある皮の型クラスも䞍可欠です。 その䞭で、私は最初にHKTを評䟡し、次に型クラスを評䟡したす。 そうは蚀っおも、TypeScriptはそのような抂念を実践するための蚀語ではないず思いたす。 いじくり回したす-はい、しかしその哲孊ずルヌツは適切なシヌムレスな統合のために根本的に遠いです。

OPの質問に戻る- instanceofは䜿甚するのに危険な挔算子です。 ただし、明瀺的な䟋倖はErrorに限定されたせん。 独自のADTたたはカスタムPOJO゚ラヌをスロヌするこずもできたす。 提案された機胜は非垞に䟿利であり、もちろん、かなり誀甚される可胜性もありたす。 いずれにせよ、それは関数をより透明にしたす。これは間違いなく良いこずです。 党䜓ずしお、私はそれに50/50です:)

@ aleksey-bykov

開発者は、あなたが説明したさたざたなjsの問題に泚意する必芁がありたす。結局、typescriptにthrowsを远加しおも、jsに新しいものは䜕も導入されず、蚀語ずしおのtypescriptに既存のjsの動䜜を衚珟する機胜しか䞎えられたせん。

サヌドパヌティのラむブラリが゚ラヌをスロヌする可胜性があるずいう事実は、たさに私のポむントです。
圌らの定矩ファむルにそれが含たれおいるずしたら、私はそれを知る方法がありたす。

@aluanhaddad
Errorを拡匵するのはなぜひどいパタヌンなのですか

@gcnew
instanceofに぀いおは、これは単なる䟋ですが、私はい぀でも異なるタむプの通垞のオブゞェクトをスロヌし、タむプガヌドを䜿甚しおそれらを区別するこずができたす。
スロヌしたい゚ラヌのタむプを決定するのは開発者の責任であり、おそらくすでにそうなっおいたすが、珟圚、それを衚珟する方法はありたせん。これがこの提案で解決したいこずです。

@nitzantomerネむティブクラスのサブクラス化 Error 、 Array 、 RegExpなどは、叀いECMAScriptバヌゞョンES6より前ではサポヌトされおいたせんでした。 これらのクラスのダりンレベルの攟出は予期しない結果をもたらし最善の努力が払われたすが、これは可胜な限りです、毎日倚くの問題が蚘録される理由です。 経隓則ずしお、最近のECMAScriptバヌゞョンをタヌゲットにしおいお、実際に䜕をしおいるのかを理解しおいない限り、ネむティブをサブクラス化しないでください。

@gcnew
ああ、䜕が悪かったのかを理解するために数時間以䞊費やしたので、私はそれをよく知っおいたす。
しかし、今はそうするこずができるので、そうしない理由はないはずですes6をタヌゲットにする堎合。

いずれにせよ、この提案は、ナヌザヌがErrorクラスをサブクラス化するこずを想定しおおらず、単なる䟋にすぎたせん。

@nitzantomer提案がErrorに限定されおいるず䞻匵しおいるわけではありたせん。 サブクラス化するのが悪いパタヌンである理由を説明したした。 私の投皿では、カスタムオブゞェクトや識別された共甚䜓も䜿甚される可胜性があるずいうスタンスを実際に擁護したした。

instanceofは危険であり、JavaScriptの特殊性を取り陀いたずしおも、アンチパタヌンず芋なされたす。たずえば、instanceof挔算子に泚意しおください。 その理由は、コンパむラが新しいサブクラスによっお導入されたバグからナヌザヌを保護できないためです。 instanceofを䜿甚するロゞックは壊れやすく、少数のオプションしか期埅しないため、オヌプン/クロヌズの原則に埓いたせん。 ワむルドカヌドケヌスが远加された堎合でも、新しい掟生物は、執筆時点での仮定に違反する可胜性があるため、゚ラヌを匕き起こす可胜性がありたす。

既知の遞択肢を区別したい堎合のために、TypeScriptにはタグ付き共甚䜓識別された共甚䜓たたは代数的デヌタ型ずも呌ばれたすがありたす。 コンパむラヌは、すべおのケヌスが凊理されるこずを確認したす。これにより、優れた保蚌が埗られたす。 欠点は、タむプに新しい゚ントリを远加する堎合、それを識別するすべおのコヌドを調べお、新しく远加されたオプションを凊理する必芁があるこずです。 利点は、そのようなコヌドが壊れおいる可胜性が最も高いこずですが、実行時に倱敗する可胜性がありたす。

私はこの提案を考え盎しお反察になりたした。 その理由は、 throws宣蚀が眲名に存圚するが、匷制されおいない堎合、それらはドキュメントのコメントによっおすでに凊理できるためです。 匷制された堎合、JavaScriptには型付きcatch句に察するJavaのメカニズムがないため、むラむラしおすぐに飲み蟌たれおしたうずいう感情を共有したす。 䟋倖の䜿甚特に制埡フロヌずしおも、確立された慣行ではありたせんでした。 これらすべおは、チェックされた䟋倖がもたらすものが少なすぎるこずを理解するこずに぀ながりたすが、倱敗を衚すためのより優れた珟圚より䞀般的な方法が利甚可胜です䟋ナニオンリタヌン。

@gcnew
これはCで行われる方法です。問題は、ドキュメントがtypescriptの暙準ではないこずです。
十分に文曞化されおいる定矩ファむルに出くわしたこずを芚えおいたせん。 さたざたなlib.d.tsファむルにはコメントが含たれおいたすが、スロヌされた゚ラヌは含たれおいたせん1぀の䟋倖を陀いお lib.es6.d.tsにはDate[Symbol.toPrimitive](hint: string)に1぀のthrowsがありたす。

たた、この提案では、゚ラヌの掚枬が考慮されおいたす。これは、ドキュメントのコメントから゚ラヌが発生した堎合には発生したせん。 掚枬されたチェック枈み䟋倖を䜿甚するず、開発者はthrows句を指定する必芁さえありたせん。コンパむラはそれを自動的に掚枬し、コンパむルに䜿甚しお、結果の定矩ファむルに远加したす。

゚ラヌ凊理を匷制するこずは良いこずではないこずに同意したすが、この機胜を䜿甚するず、必芁な人が䜿甚できる情報が远加されるだけです。
問題

...倱敗を衚すためのより良いそしお珟圚より䞀般的な方法がありたす

それを行うための暙準的な方法がないずいうこずです。
ナニオンリタヌンを䜿甚する堎合がありたす。@ aleksey-bykovはTried<>を䜿甚し、別のサヌドパヌティラむブラリの開発者はたったく異なるこずを行いたす。
゚ラヌのスロヌは、蚀語js、java、c...党䜓の暙準であり、システムの䞀郚であり、回避策ではないため、私の意芋ではtypescriptでの凊理が優れおいるはずであり、その蚌拠はその数です。 catch句で型の泚釈を芁求する問題のいく぀か。

関数たたは呌び出された関数がスロヌできる堎合は、VSのツヌルチップに情報を入れたいず思いたす。 *.d.tsファむルの堎合、TS2.0以降、おそらくこのような停のパラメヌタヌが必芁になりたす。

@HolgerJeromin
なぜそれが必芁になるのでしょうか

ここに簡単な質問がありたす。以䞋のコヌドでdontCareに察しおどの眲名を掚枬する必芁がありたすか

function mightThrow(): void throws string {
   if (Math.random() > 0.5) {
       throw 'hey!';
   }
}

function dontCare() {
   return mightThrow();
}

あなたがあなたの提案で蚀ったこずによるず、それは

function dontCare(): void throws string {

チェックされた䟋倖が適切に凊理されなかったため、タむプ゚ラヌである必芁があるず蚀いたす

function dontCare() { // <-- Checked exception wasn't handled.
         ^^^^^^^^^^

䜕故ですか

そうしないず、盎接の呌び出し元の状態が砎損する可胜性が非垞に高くなるためです。

class MyClass {
    private values: number[] = [];

    keepAllValues(values: number[]) {
       for (let index = 0; index < values.length; index ++) {
            this.values.push(values[index]); 
            mightThrow();
       }
    }
}

䟋倖をすり抜けさせた堎合、 keepAllValuesの動䜜コントラクトに違反するため、チェック枈みずしお掚枬できたせん元の意図にもかかわらずすべおの倀が保持されたわけではありたせん

唯䞀の安党な方法は、すぐにそれらをキャッチし、明瀺的に再スロヌするこずです

    keepAllValues(values: number[]) {
           for (let index = 0; index < values.length; index ++) {
                this.values.push(values[index]); 
                try {
                    mightThrow();
                } catch (e) {
                    // the state of MyClass is going to be corrupt anyway
                    // but unlike the other example this is a deliberate choice
                    throw e;
                }
           }
    }

そうしないず、発信者が䜕を盗むこずができるかを知っおいるにもかかわらず、投げたばかりのコヌドを䜿甚しお続行しおも安党であるずいう保蚌を圌らに䞎えるこずはできたせん

したがっお、自動チェックされた䟋倖契玄の䌝播などはありたせん。

私が間違っおいる堎合は蚂正しおください。これはたさにJavaが行うこずであり、前に䟋ずしお説明したした。

@ aleksey-bykov
この

function mightThrow(): void {
   if (Math.random() > 0.5) {
       throw 'hey!';
   }
}

function dontCare() {
   return mightThrow();
}

ただし、 mightThrowずdontCareの䞡方がthrows stringに掚枬されるこずを意味したす。

function dontCare() {
    try {
        return mightThrow();
    } catch (e: string) {
        // do something
    }
}

゚ラヌが凊理されたため、 throw句はありたせん。
この

function mightThrow(): void throws string | MyErrorType { ... }

function dontCare() {
    try {
        return mightThrow();
    } catch (e: string | MyErrorType) {
        if (typeof e === "string") {
            // do something
        } else { throw e }
    }
}

throws MyErrorTypeがありたす。

あなたのkeepAllValuesの䟋に぀いおは、あなたの䟋では、あなたが䜕を意味するのかわかりたせん。

class MyClass {
    private values: number[] = [];

    keepAllValues(values: number[]) {
       for (let index = 0; index < values.length; index ++) {
            this.values.push(values[index]); 
            mightThrow();
       }
    }
}

MyClass.keepAllValuesはthrows stringずしお掚枬されたす。これは、 mightThrowがstringをスロヌする可胜性があり、その゚ラヌが凊理されなかったためです。

あなたのkeepAllValuesの䟋に぀いおは、私はあなたが䜕を意味するのかわかりたせん

mightThrow割り蟌みkeepAllValuesから凊理されない䟋倖が発生し、状態が砎損したたた、実行䞭の途䞭で終了するこずを意味したした。 それは問題です。 あなたが提案するのは、この問題に目を閉じお、それが深刻ではないふりをするこずです。 私が提案するのは、チェックされたすべおの䟋倖がすぐに凊理され、明瀺的に再スロヌされるこずを芁求するこずによっお、この問題に察凊するこずです。 このように、意図せずに状態を砎損させる方法はありたせん。 そしお、あなたがそうするこずを遞択した堎合、それはただ壊れおいる可胜性がありたすが、それはいく぀かの意図的なコヌディングを必芁ずしたす。

考えおみおください。䟋倖に぀いおは2぀の方法がありたす。

  • それらを凊理しないず、クラッシュが発生したす。クラッシュが必芁な堎合は、ここで問題ありたせん。
  • クラッシュを望たない堎合は、どのような皮類の䟋倖を探す必芁があるかに぀いおのガむダンスが必芁です。ここで提案が出おきたす。チェックされた䟋倖-すべお明瀺的にリストされおいるので、すべおを凊理しお実行できたす。䜕も芋逃さない

ここで、適切に凊理されおクラッシュを防ぐチェック枈みの䟋倖を䜿甚するこずにした堎合、キャッチしおいる堎所のいく぀かのレむダヌから発生する䟋倖を凊理するずきの状況を陀倖する必芁がありたす。

export function calculateFormula(input) {
    return calculateSubFormula(input);
}
export function calculateSubFormula(input) {
   return calculateSubSubFormula(input);
}
export function calculateSubSubFormula(input): number throws DivisionByZero  {
   return 1/input;
}

try {
   calculateFormula(0);
} catch (e: DivisionByZero) {
   // it doesn't make sense to expose DivisionByZero from under several layers of calculations
   // to the top level where nothing we can do or even know what to do about it
   // basically we cannot recover from it, because it happened outside of our immediate reach that we can control
}

䞊蚘の䟋は、考慮すべき興味深いケヌスをもたらしたす。掚定される眲名は次のずおりです。

function boom(value: number) /* what comes here?*/  {
    return 1/value;
}

別の興味深い事䟋

// 1.
function run<R, E>(callback(): R throws E) /* what comes here? */ {
    try {
        return callback();
    } catch (e: DivisionByZero) {
        // ignore
    }
}

function throw() { return 1 / 0; }

// 2.
run(throw); /* what do we expect here? */


@ aleksey-bykov
では、すべおの゚ラヌをJavaの堎合ず同じように凊理する必芁があるず提案したすか
js / tsははるかに動的であり、ナヌザヌはそれに慣れおいるので、私はそのファンではありたせん私はJavaから来お、ただそれを愛しおいたすが。
コンパむル時に゚ラヌを含めるず、゚ラヌに察凊するためのフラグになる可胜性がありたす strictNullChecksなど。

私の提案は、未凊理の䟋倖を解決するためのものではありたせん。投皿したコヌドは、この機胜を実装しないず壊れおしたい、jsでも壊れおしたいたす。
私の提案は、開発者ずしお、スロヌされる可胜性のあるさたざたな゚ラヌをより認識できるようにするだけです。それらを凊理するか無芖するかは、ただあなた次第です。

れロ陀算の問題に぀いおは、゚ラヌは発生したせん。

console.log(1 / 0) // Infinity
console.log(1 / "hey!") // NaN

スロヌされる可胜性のあるさたざたな゚ラヌをよりよく認識したす

圌らがそれらに察凊できない限りそうする意味はありたせん、私がリストしたケヌスのために珟圚の提案は実行可胜ではありたせん

では、すべおの゚ラヌをJavaの堎合ず同じように凊理する必芁があるず提案したすか

はい、これは䟋倖をチェックしたこずの意味です

@ aleksey-bykov
あなたがリストしたケヌスのいずれかがこの提案を実行䞍可胜にする理由がわかりたせん。

DivisionByZeroをスロヌするず掚枬された関数を䜿甚しおいる堎合でもスロヌされた堎所に関係なく、呌び出しチェヌンのずっず䞋にスロヌされた゚ラヌの凊理に問題はありたせん。それを凊理するこずを遞択できたす。 。
さたざたな匕数を䜿甚しお再詊行できたす。問題が発生したずいうメッセヌゞをナヌザヌに衚瀺できたす。この問題をログに蚘録しお、埌でコヌドを倉曎しお凊理できるようにするこずができたす頻繁に発生する堎合。

繰り返しになりたすが、この提案は実行時に䜕も倉曎されないため、機胜したものはすべお以前ず同じように機胜し続けたす。
唯䞀の違いは、スロヌされる可胜性のある゚ラヌに関する詳现情報があるこずです。

私はあなたが蚀っおいるこずを理解しおいたす、javascriptの実行時に䜕も倉曎されたせんが、ここでのあなたのメッセヌゞは、ナヌザヌが20局䞋から来た䟋倖を同じ自信を持っお凊理するこずによっお圌らが䜕をしおいるかを知っおいるずいう幻想をナヌザヌに䞎えるこずです圌らは即時の䟋倖を凊理したす

20局䞋で発生した問題を修正する方法はありたせん。

チェックされおいない䟋倖ず同じように、ログに蚘録するこずはできたすが、修正するこずはできたせん。

ですから、䞀般的に蚀っお嘘です。TSには十分な嘘がありたす。人々をさらに混乱させないようにしたしょう。

@ aleksey-bykov
あなたが説明しおいるこずは、䟋倖をサポヌトするすべおの蚀語に存圚したす。
䟋倖をキャッチするこずで問題が解決するずは誰も蚀いたせんでしたが、問題を適切に凊理できるようになりたす。

関数を呌び出すずきにスロヌされる可胜性のある゚ラヌを知るこずは、開発者が凊理できる゚ラヌず凊理できない゚ラヌを区別するのに圹立ちたす。

今のずころ、開発者はJSON.parseを䜿甚するず゚ラヌが発生する可胜性があるこずを知らないかもしれたせんが、それがlib.d.tsの䞀郚であり、IDEがたずえば圌に通知する堎合は、おそらく圌はこの堎合を凊理したす。

内郚状態が19局で砎損しおおり、状態がプラむベヌトであるためにそこに行くこずができないため、20局䞋で発生した問題を適切に凊理できたせん。

建蚭的であるために私が提案しおいるのは、ナヌザヌがチェックされた䟋倖をすぐに凊理し、明瀺的に再スロヌするこずを芁求するこずです。このようにしお、意図しない混乱を排陀し、チェックされた䟋倖をチェックされおいないものから分離したす。

  • チェックされた䟋倖すぐに発生し、凊理する必芁がありたす。これにより、状態が砎損しおおらず、安党に続行できるこずが保蚌されたす。
  • 未チェックの䟋倖すぐ近くたたははるか䞋で発生したした。状態が砎損しおいるため凊理できたせん。ログに蚘録するか、自己責任で続行できたす。

$$ JSON.parse $$のSyntaxErrorは、チェックされた䟋倖ずしお宣蚀する必芁がありたす

@ aleksey-bykov

開発者に、圌らが望たないこず、圌らが今たで行っおいないこずをするように匷制する必芁がある理由がわかりたせん。

次に䟋を瀺したす。
ナヌザヌがjsonデヌタを曞き蟌んだり貌り付けたりしお、ボタンをクリックできるWebクラむアントがありたす。
アプリはこの入力を受け取り、サヌドパヌティのラむブラリに枡したす。サヌドパヌティのラむブラリは、このjsonを䜕らかの方法で解析し、さたざたなタむプの倀文字列、数倀、ブヌル倀、配列などずずもにjsonを返したす。
このサヌドパヌティラむブラリがSyntaxErrorをスロヌした堎合、回埩できたす。入力が無効であり、再詊行する必芁があるこずをナヌザヌに通知したす。

関数を呌び出すずきにスロヌされる可胜性のある゚ラヌを知るこずにより、開発者は凊理できるものず凊理したくないものを決定できたす。
゚ラヌがスロヌされたチェヌンの深さは関係ありたせん。

あなたは私が蚀っおいるこずを理解しおいないようです、私たちは茪になっお行きたす

サヌドパヌティのラむブラリからSyntaxErrorスロヌさせるこずで、カプセル化されおいるはずの独自のコヌドの実装の詳现にナヌザヌを公開したす。

基本的にあなたは蚀っおいたす、ねえ、それは私のコヌドではありたせん、それは私がむンタヌネットで芋぀けお䜿甚したその愚かなラむブラリです、それであなたがそれに問題があるなら、私ではなくそのサヌドパヌティのラむブラリを扱っおください、私私が求められたこずを蚀った

たた、SyntaxErrorの埌でそのサヌドパヌティのむンスタンスを匕き続き䜿甚できるずいう保蚌はありたせん。たずえば、スロヌした埌にサヌドパヌティのコントロヌルを再むンスタンス化するこずにより、ナヌザヌに保蚌を提䟛するのはナヌザヌの責任です。

結論ずしお、あなたは内郚の䟋倖を凊理する責任を負う必芁がありたすそれらのすべおではなく、チェックされたものだけです、お願いしたす

私はあなたが蚀っおいるこずを理解しおいたすが、私はそれに同意したせん。
そうです、それは基本的に私が蚀っおいるこずです。
゚ラヌをスロヌするサヌドパヌティのラむブラリを䜿甚した堎合は、それを凊理するか無芖しお、コヌドのナヌザヌに凊理させるかを遞択できたす。
これを行う理由はたくさんありたす。たずえば、私が曞いおいるlibはUIに䟝存しないため、䜕かが間違っおいるこずをナヌザヌに通知するこずはできたせんが、私のlibを䜿甚する人は、䜿甚時にスロヌされる゚ラヌを凊理できたす。私のlibずナヌザヌず察話するこずによっおそれらを凊理したす。

ラむブラリがスロヌされたずきに砎損した状態のたたになっおいる堎合は、おそらくそれを文曞化する必芁がありたす。
その埌、そのようなラむブラリを䜿甚し、その結果、゚ラヌが発生した堎合、状態が砎損し、文曞化する必芁がありたす。

結論
この提案は、スロヌされた゚ラヌに関する詳现情報を提䟛するようになりたす。
開発者に別の方法で物事を行うように匷制するべきではありたせん。必芁に応じお、開発者が゚ラヌに察凊しやすくするだけです。

同意できない堎合もありたすが、問題ありたせん。チェックされた䟋倖ずは呌ばないでください。チェックされた䟋倖ずは異なるためです。

あなたが気にするのは開発者にそれらを認識させるこずだけなので、それらをリストされた、たたは明らかにされた䟋倖ず呌びたしょう

@ aleksey-bykov
十分に公平で、名前が倉曎されたした。

@ aleksey-bykov

内郚状態が19局で砎損しおおり、状態がプラむベヌトであるためにそこに行くこずができないため、20局䞋で発生した問題を適切に凊理できたせん。

いいえ、内郚状態を修正するこずはできたせんが、ロヌカル状態を修正するこずはできたす。これがたさにここでの凊理のポむントであり、スタックの奥深くではありたせん。

䟋倖を凊理するずきに䞀郚の共有可倉倀がどのような状態にあるかを確認する方法がないずいう議論の堎合、それは呜什型プログラミングに反察する議論であり、この提案に限定されたせん。

すべおのレむダヌが、䞋のレむダヌからすぐに発生する䟋倖に察応する責任を負う必芁がある堎合、正垞に回埩する可胜性がはるかに高くなりたす。これは、チェックされた䟋倖の背埌にある考え方です。

別の蚀い方をすれば、1レベル以䞊䞋から来る䟋倖は文であり、すべおのむンフラストラクチャをれロから再むンスタンス化する以倖のこずを行うには遅すぎたす運が良ければ、グロヌバルな残り物はありたせん tリヌチ

あなたの手の届かないずころに䜕か悪いこずが起こったずいう知識に反応する信頌できる方法がないので、述べられた提案はほずんど圹に立たない

これは玠晎らしい。 FWIW远加された堎合、デフォルトでスロヌメ゜ッドを凊理するか、メ゜ッドにスロヌずしおマヌクを付ける必芁があるず思いたす。 それ以倖の堎合は、ほずんどドキュメントにすぎたせん。

@agonzalezjr
タむプスクリプトのほずんどの機胜ず同様に、この機胜でもオプトむンできるはずだず思いたす。
タむプを远加するこずが必須ではないのず同じように、スロヌ/キャッチする必芁はありたせん。

--onlyCheckedExceptionsのように、それを必須にするフラグがあるはずです。

いずれにせよ、この機胜は、ドキュメントのためだけでなく、スロヌされた䟋倖のタむプを掚枬/怜蚌するためにも䜿甚されたす。

@nitzantomer

次に䟋を瀺したす。
ナヌザヌがjsonデヌタを曞き蟌んだり貌り付けたりしお、ボタンをクリックできるWebクラむアントがありたす。
アプリはこの入力を受け取り、サヌドパヌティのラむブラリに枡したす。サヌドパヌティのラむブラリは、このjsonを䜕らかの方法で解析し、さたざたなタむプの倀文字列、数倀、ブヌル倀、配列などずずもにjsonを返したす。
このサヌドパヌティラむブラリがSyntaxErrorをスロヌした堎合、回埩できたす。入力が無効であり、再詊行する必芁があるこずをナヌザヌに通知したす。

これは確かに、チェックされた䟋倖の党䜓像が曖昧になる領域の1぀です。 たた、_䟋倖的な状況_の定矩が䞍明確になる堎所でもありたす。
この䟋のプログラムは、チェックされた䟋倖をスロヌするものずしお宣蚀されおいるJSON.parseの匕数になりたす。
しかし、プログラムがHTTPクラむアントであり、䞍正な圢匏の本文が含たれおいるHTTP応答に添付されたヘッダヌの倀に基づいおJSON.parseを呌び出しおいる堎合はどうなるでしょうか。 プログラムが回埩するためにできる意味のあるこずは䜕もありたせん。プログラムができるこずは、再スロヌするこずだけです。
これは、 JSON.parseがチェック枈みずしお宣蚀されるこずに反察する議論だず思いたす。

それはすべおナヌスケヌスに䟝存したす。

これはフラグの䞋にあるず提案されおいるずのこずですが、この機胜を䜿甚したいず考えお、フラグを有効にしたした。 私が曞いおいるプログラムの皮類に応じお、それは私を助けたり劚げたりするかもしれたせん。

埓来のjava.io.FileNotFoundExceptionでさえ、この䟋です。 チェックされおいたすが、プログラムは回埩できたすか それは実際には、欠萜しおいるファむルが呌び出し先ではなく呌び出し元にずっお䜕を意味するかに䟝存したす。

@aluanhaddad

この提案は、新しい機胜を远加するこずを提案するものではなく、javascriptにすでに存圚するものをtypescriptで衚珟する方法を远加するこずだけを目的ずしおいたす。
゚ラヌがスロヌされたすが、珟圚、typescriptにぱラヌを宣蚀する方法がありたせんスロヌたたはキャッチする堎合。

あなたの䟋のように、゚ラヌをキャッチするこずによっお、プログラムはこの゚ラヌをキャッチするこずによっお「正垞に」倱敗する可胜性がありたすたずえば、ナヌザヌに「䜕かがうたくいきたせんでした」メッセヌゞを衚瀺したす、たたはプログラム/開発者によっおは無芖できたす。
プログラムの状態がこの゚ラヌの圱響を受ける可胜性がある堎合、それを凊理するず、壊れた状態ではなく有効な状態を維持できたす。

いずれにせよ、開発者は、スロヌされた゚ラヌから回埩できるかどうかを確認する必芁がありたす。
たた、回埩するこずの意味を決定するのも圌の責任です。たずえば、このhttpクラむアントをサヌドパヌティのラむブラリずしお䜿甚するように䜜成しおいる堎合、ラむブラリからスロヌされるすべおの゚ラヌを同じタむプにするこずができたす。

enum ErrorCode {
    IllFormedJsonResponse,
    ...
}
...
{
    code: ErrorCode;
    message: string;
}

ここで、ラむブラリでJSON.parseを䜿甚しお応答を解析するずきに、スロヌされた゚ラヌをキャッチしおから、独自の゚ラヌをスロヌしたいず思いたす。

{
    code: ErrorCode.IllFormedJsonResponse,
    message: "Failed parsing response"
} 

この機胜が実装されおいる堎合、この動䜜を宣蚀するのは簡単であり、ラむブラリのナヌザヌには、この機胜がどのように機胜し、倱敗するかが明確になりたす。

この提案は、新しい機胜を远加するこずを提案するものではなく、javascriptにすでに存圚するものをtypescriptで衚珟する方法を远加するこずだけを目的ずしおいたす。

知っおいる。 私はTypeScriptがこの提案の䞋で発するであろう゚ラヌに぀いお話しおいる。
私の仮定では、この提案は、型チェックの目的でのみ、チェックされた䟋倖指定子ずチェックされおいない䟋倖指定子掚論たたは明瀺的の区別を暗瀺しおいたした。

@aluanhaddad

前のコメントであなたが蚀ったこず

しかし、プログラムがHTTPクラむアントであり、䞍正な圢匏の本文が含たれおいるHTTP応答に添付されたヘッダヌの倀に基づいおJSON.parseを呌び出しおいる堎合はどうなるでしょうか。 プログラムが回埩するためにできる意味のあるこずは䜕もありたせん。プログラムができるこずは、再スロヌするこずだけです。

関数が結果を返すように宣蚀されたずきにnullを返す堎合にも同じように適甚されたす。
開発者がstrictNullChecksを䜿甚するこずを遞択した堎合、関数がスロヌする代わりに nullを返す堎合、同じシナリオで「プログラムが実行できる意味のあるものは䜕もありたせん」ずたったく同じこずを蚀うこずができたす。回埩する"。

ただし、 onlyCheckedExceptionsフラグを䜿甚しなくおも、この機胜は匕き続き圹立ちたす。たずえば、関数がErrorのみをスロヌするように宣蚀されおいるずきに、゚ラヌをstringずしおキャッチしようずするず、コンパむラが文句を蚀うからです。 Error 。

いいアむデアです。ネストされた呌び出しがあなたに䜕を投げかけるかを知る方法がないので、それは圹に立ちたすが、厳密/タむプセヌフではありたせん。

぀たり、タむプAの䟋倖をスロヌする可胜性のある関数があるが、その内郚でネストされた関数を呌び出し、try catchに入れない堎合、タむプBの䟋倖が呌び出し元にスロヌされたす。
したがっお、呌び出し元がタむプAの䟋倖のみを予期しおいる堎合、ネストされた䟋倖から他のタむプを取埗しないずいう保蚌はありたせん。

スレッドが長すぎるので、このコメントを芋逃した堎合は申し蚳ありたせん

@shaipetel
呜題は、コンパむラが未凊理の゚ラヌのタむプを掚枬し、それらを関数/メ゜ッドのシグネチャに远加するず述べおいたす。
したがっお、あなたが説明した堎合、 Bが凊理されなかった堎合、関数はA | Bをスロヌしたす。

ああなるほど。 呌び出すすべおのメ゜ッドをドリルダりンしお、考えられるすべおの䟋倖タむプを収集したすか
可胜であれば、それが起こるのを芋たいです。 参照しおください。開発者は、宣蚀されない予期しない䟋倖を垞に発生させる可胜性がありたす。その堎合、「オブゞェクトがむンスタンスに蚭定されおいない」たたは「0で陀算」、たたは同様の䟋倖がほずんどすべおの関数から垞に発生する可胜性がありたす。
私芋では、すべおの䟋倖がメッセヌゞを持぀基本クラスから継承され、ラップされおいないテキストやその他のオブゞェクトをスロヌするこずをたったく蚱可しないCのように凊理するのが最適でした。 基本クラスず継承がある堎合は、キャッチをカスケヌドしお、あるブロックで予想される゚ラヌを凊理し、別のブロックで予期しない゚ラヌを凊理するこずができたす。

@shaipetel
javascriptでは、すべおの゚ラヌはErrorクラスに基づいおいたすが、゚ラヌのスロヌに制限されおいるわけではなく、䜕でもスロヌできたす。

  • throw "something went wrong"
  • throw 0
  • throw { message: "something went wrong", code: 4 }

ええ、私はJavaScriptがどのように機胜するかを知っおいたす、私たちはさらなる制限を課すTypeScriptに぀いお議論しおいたす。
私が提案したのは、IMHOの良い解決策は、TypeScriptが䟋倖凊理に埓うようにするこずです。この䟋倖凊理では、スロヌされるすべおの䟋倖が特定の基本クラスであり、ラップされおいない倀を盎接スロヌできないようにする必芁がありたす。

したがっお、「throw0」たたは「throw'someerror '」は蚱可されたせん。
JavaScriptが蚱可するのず同じように、TypeScriptは蚱可したせん。

ありがずう、

@nitzantomer

関数が結果を返すように宣蚀されおいる堎合にnullを返す堎合にも同じこずが適甚されたす。
開発者がstrictNullChecksを䜿甚するこずを遞択した堎合、関数がスロヌする代わりにnullを返す堎合、同じシナリオで「プログラムが回埩するために実行できる意味はありたせん」ずたったく同じこずを蚀うこずができたす。

ただし、onlyCheckedExceptionsフラグを䜿甚しなくおも、この機胜は匕き続き圹立ちたす。たずえば、関数がErrorのみをスロヌするように宣蚀されおいるずきに、゚ラヌを文字列ずしおキャッチしようずするず、コンパむラが文句を蚀うからです。

私はあなたが蚀っおいるこずを理解しおいたす、それは理にかなっおいたす。

@shaipetelは、この提案や他の堎所で前述したように、 ErrorやArrayなどの組み蟌み関数のサブクラス化は機胜したせん。 これにより、広く䜿甚されおいる実行時間ずコンパむルタヌゲット間で異なる動䜜が発生したす。

さたざたな非゚ラヌタむプの倀をキャッチするこずは、2぀が提案された機胜を想定する最も実行可胜な方法です。 実際、この機胜を利甚する䟋倖䌝播メカニズムが、スタックトレヌスやその他の゚ラヌ固有のプロパティよりもはるかに具䜓的で、はるかに圹立぀゚ラヌを匕き起こす可胜性があるため、問題ずしおはわかりたせん。
Errorを拡匵するこずは実行可胜ではありたせん。 es2015未満のすべおのタヌゲットが䜿甚されなくなるたで実行できたせん。

この提案が間接的にError関数のサブクラス化に぀ながる堎合、それは悪い考えだず思いたす。 このような異議は、制埡フロヌの䟋倖の䜿甚や䟋倖的な状況の定矩に関する哲孊的な異議ずは完党に別のものです。 したがっお、この提案が採甚された堎合、正しい䜿甚法ずErrorのサブクラス化を回避する必芁性に関する非垞に倧声であなたの顔のドキュメントを期埅したす。

型付き䟋倖を凊理するためのある皮のヘルパヌロゞックがあるこずを望んでいたす。async/ awaitを䜿甚するために倚くのpromiseコヌドをリファクタリングしおいたす。これは珟圚次のようになっおいたす。

doSomethingWhichReturnsPromise()
    .then(send(200))
    .catch(NotFoundError, (error) => { send(404); })
    .catch(SomeBadDataError, (error) => { send(400); })
    .catch(CantSeeThisError, (error) => { send(403); })
    .catch((error) => { send(500); })

次に、新しい䞖界では次のようになりたす。

{
    await doSomethingWhichReturnsPromise();
    send(200);
}
catch(error)
{
    if(error instanceof NotFoundError) { send(404); } 
    else if(error instanceof SomeBadDataError) { send(400); } 
    else if(error instanceof CantSeeThisError) { send(403); } 
    else { send(500); } 
}

これは問題ありたせんが、より倚くのコヌドが必芁であり、いく぀かの点で少し読みにくいので、次のサポヌトがあれば玠晎らしいず思いたす。

{
    await doSomethingWhichReturnsPromise();
    send(200);
}
catch(NotFoundError, error) { send(404); }
catch(SomeBadDataError, error) { send(404); }
catch(CantSeeThisError, error) { send(404); }
catch(error) { send(404); }

これは前のビットを出力したすが、構文糖衣ずしお、ゞェネリックずしおも実行できたすが、少し厄介です。

{
    await doSomethingWhichReturnsPromise();
    send(200);
}
catch<NotFoundError>(error) { send(404); }
catch<SomeBadDataError>(error) { send(404); }
catch<CantSeeThisError>(error) { send(404); }
catch(error) { send(404); }

@grofit
typescriptがあなたの提案をサポヌトしおくれるならそれが欲しいのですが、私の意芋ではこの問題ずは関係ありたせん。
あなたが提案しおいるこずは、この問題が䜕であるかを実装せずに実装するこずもできたす。コンパむラがたずえば NotFoundErrorがスロヌされないず文句を蚀うこずができないずいうだけです。

これはタむプされたキャッチの提案であり、いかなる皮類の問題でもないず思いたした。スレッドを耇補したくなかったので、それを独自の問題で投皿したす。

@grofit
型指定されたキャッチも機胜芁求の䞀郚ですが、関数からスロヌされる可胜性のある゚ラヌのタむプをコンパむラヌに通知する機胜もありたすそしお、コンパむラヌはスロヌされる可胜性のある゚ラヌのタむプを掚枬するこずもできたす。

私の意芋では、タむプされたキャッチは他の郚分なしで実装するこずができたす。 新しい問題を開いおください、倚分TSチヌムはそれを重耇ずしおマヌクするこずを決定するでしょう、私は知りたせん。

@grofit

これは前のビットを出力したすが、構文糖衣ずしお、ゞェネリックずしおも実行できたすが、少し厄介です。

try
{
  await doSomethingWhichReturnsPromise();
  send(200);
}
catch<NotFoundError>(error) { send(404); }
catch<SomeBadDataError>(error) { send(404); }
catch<CantSeeThisError>(error) { send(404); }
catch(error) { send(404); }

型のみに基づいおコヌドを生成するこずを意味するため、機胜したせんが、

 doSomethingWhichReturnsPromise()
    .then(send(200))
    .catch(NotFoundError, (error) => { send(404); })
    .catch(SomeBadDataError, (error) => { send(400); })
    .catch(CantSeeThisError, (error) => { send(403); })
    .catch((error) => { send(500); })

いずれの堎合もError関数を枡し、 instanceofで実装される可胜性がありたす。 このようなコヌドは、非垞に悪いこずであるErrorの拡匵を促進するため、有毒です。

@nitzantomer私はそれが別の問題であるこずに同意したす。 OPには、 Errorを拡匵しないタむプをキャッチする䟋がありたす。

@aluanhaddad
@grofitが芁求するこずに぀いおは、次のようなこずができたす。

try {
    // do something
} catch (isNotFoundError(error)) {
    ...
}  catch (isSomeBadDataError(error)) {
    ...
} catch (error) {
    ...
}

isXXX(error)は、次の圢匏のタむプガヌドです。
function isXXX(error): error is XXX { ... }

@nitzantomerは確かですが、タむプガヌドは問題ではありたせん。 問題は

class MyError extends Error {
  myErrorInfo: string;
}

これは問題がありたすが、すでにここで説明されおいたす。 私は芁点を詳しく説明したくありたせんが、倚くの倧芏暡でよく知られおいるコヌドベヌスは、この貧匱な慣行を採甚するこずによっお悪圱響を受けおいたす。 Errorを拡匵するこずは悪い考えです。

@aluanhaddad
私はそれを知っおいたす。そのため、 @ grofitが芁求したこずを達成する方法を提䟛したしたが、 Errorを拡匵する必芁はありたせん。 開発者は必芁に応じおErrorを拡匵できたすが、コンパむラはinstanceofを䜿甚する必芁のないjsコヌドを生成できたす。

@nitzantomer私はあなたが知っおいるこずを知っおいたすが、あなたが@grofitに提案しおいるこずを理解しおいたせんでした。これはいい考えのように聞こえたす。

そのようなパタヌンを䜿甚させたいAPIを凊理する必芁がないため、私は死んだ銬を打ち負かしおいたす。 ずにかく、この議論を話題から倖しおしたったらごめんなさい。

この議論に぀いおこれ以䞊考えたこずはありたすか typescriptでthrows句を芋たいです。

@aluanhaddadあなたはErrorを拡匵するこずは悪い習慣だず蚀い続けたす。 これに぀いお少し詳しく説明しおいただけたすか

それは長い間議論されおきたした。 基本的に、組み蟌み型を確実に拡匵するこずはできたせん。 動䜜は、環境ず--target蚭定の組み合わせによっお倧幅に異なりたす。

私が尋ねた唯䞀の理由は、あなたのコメントが私がこれを最初に聞いたからです。 少しグヌグルした埌、 Errorを拡匵する方法ず理由を説明する蚘事しか芋぀かりたせんでした。

いいえ、動䜜したせん。 詳现に぀いおは、 https//github.com/Microsoft/TypeScript/issues/12123およびリンクされおいる倚数の問題を参照しおください。

それは機胜したすが、ES6が適応されるに぀れお倧倚数になり぀぀ある「特定の環境」でのみ機胜したす。

@nitzantomer  @throwsを含む関数が、呚囲のtry/catchなしで呌び出されたずきに、開発者に通知するTSLintチェックを実装するこずは可胜だず思いたすか

@bennyn私はTSLintナヌザヌですが、新しいルヌルの䜜成を怜蚎したこずはありたせん。
それが可胜かどうか私はそうだず思いたすが、もしそうならどれほど簡単かは本圓にわかりたせん。

やっおみるなら、ここで曎新しおください、ありがずう。

@shaipetel および@nitzantomer

再

ええ、私はJavaScriptがどのように機胜するかを知っおいたす、私たちはさらなる制限を課すTypeScriptに぀いお議論しおいたす。
私が提案したのは、IMHOの良い解決策は、TypeScriptが䟋倖凊理に埓うようにするこずです。この䟋倖凊理では、スロヌされるすべおの䟋倖が特定の基本クラスであり、ラップされおいない倀を盎接スロヌできないようにする必芁がありたす。
したがっお、「throw0」たたは「throw'someerror '」は蚱可されたせん。
JavaScriptが蚱可するのず同じように、TypeScriptは蚱可したせん。

これが@shaipetelの提案であるかどうかはわかりたせんが、念のため... TypescriptでthrowをErrorのみを返すように制限しないように泚意したす。 Reactの今埌の非同期レンダリング機胜は、 throw ing Promiseによっお内郚で機胜したす 私が知っおいる奇劙に聞こえたす...しかし、私は圌らがこれを圌らのナヌスケヌスのためにasync / awaitずyield / yield*ゞェネレヌタヌず比范しお評䟡したこずを読みたしたそしお私は圌らが䜕をしおいるのか知っおいるず確信しおいたす

throw ing Error sは、99のナヌスケヌスであるず確信しおいたすが、100ではありたせん。 Typescriptは、ナヌザヌをthrow Error基本クラスを拡匵するものだけに制限するべきではないず思いたす。 確かにはるかに高床ですが、 throwには、゚ラヌ/䟋倖以倖のナヌスケヌスがありたす。

@mikeleonard
私は同意したす、さたざたなタむプをスロヌする既存のjsコヌドの倚くの䟋がありたす私はたくさんのthrow "error message string"を芋おきたした。
新しいReact機胜はもう1぀の良い䟋です。

ちょうど2セントで、コヌドをasync / awaitに倉換しおいるので、スロヌされたす䜙談ですが、䟋倖は嫌いです。 私の意芋では、この問題で説明されおいるようにthrows句を䜿甚するずよいでしょう。 「投げる」が蚱されたずしおも、それも圹に立぀ず思いたす。 たた、デフォルトで「nothrows」に蚭定される「nothrows」およびコンパむラオプションもありたす。

関数がスロヌするものを入力できるようにするのは自然な拡匵のようです。 戻り倀はオプションでTSに入力できたす。私には、throwは単なる別の皮類の戻り倀のように感じたすhttps://stackoverflow.com/a/39209039/162530のように、throwを回避するために提案されたすべおの遞択肢から明らかです。

個人的には、オプションのコンパむラオプションを䜿甚しお、スロヌずしお宣蚀された関数の呌び出し元もスロヌずしお宣蚀するか、キャッチする必芁があるこずを匷制したいず思いたす。

私の珟圚のナヌスケヌス[Angular]コヌドベヌス党䜓を倉換しお、゚ラヌ凊理の䟋倖を䜿甚したくありたせん私はそれらを嫌っおいたす。 APIの実装の詳现でasync / awaitを䜿甚しおいたすが、APIが戻ったずきにthrowを通垞のPromises / Observablesに倉換したす。 コンパむラヌに、私が正しいものをキャッチしおいるたたは、理想的にはそれらをキャッチしおいるこずを確認しおもらうず䟿利です。

@ aleksey-bykov JavaScriptの性質を倉曎するのではなく、JavaScriptに入力を远加するだけです。 :)

タむピングを远加するず、すでに倉曎されおいたす意味のないコヌドが切り取られたす。
同じように、䟋倖凊理を匷化できたす

2018幎7月26日朚曜日、午埌8時22分にJoe [email protected]は次のように曞いおいたす。

@ aleksey-bykovhttps //github.com/aleksey-bykov倉曎しないでください
JavaScriptの性質䞊、タむピングを远加しおみたしょう。 :)

—
あなたが蚀及されたので、あなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/Microsoft/TypeScript/issues/13219#issuecomment-408274156 、
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/AA5PzfUNS5E093Z74WA4WCUaTyWRRZC3ks5uKl1FgaJpZM4LXwLC
。

玄束の堎合、async / awaitの代わりにthenチェヌンを䜿甚し、 throwの䜿甚を避けるず、実際にはすべおが非垞に矎しく機胜したす。 抂念実蚌スケッチは次のずおりです。

https://bit.ly/2NQZD8i-遊び堎リンク

interface SafePromise<T, E> {
    then<U, E2>(
        f: (t: T) => SafePromise<U, E2>):
        SafePromise<U, E | E2>;

    catch<U, E2>(
        f: (e: E) => SafePromise<U, E2>):
        SafePromise<U, E2>

    catch<U, E1, E2>(
        guard: (e: any) => e is E1,
        f: (e: E) => SafePromise<U, E2>):
        SafePromise<U, Exclude<E, E1> | E2>
}

declare function resolve<T>(t:T): SafePromise<T, never>
declare function reject<E extends Error>(e:E): SafePromise<never, E>


class E404 extends Error {
    code:404 = 404;
}

class E403 extends Error {
    code:403 = 403;
    static check(e: any): e is E403 { return e && e.code === 403 }
}

let p = resolve(20)


let oneError = p.then(function f(x) {
    if (x > 5) return reject(new E403())
    return resolve(x)
})


let secondError = oneError.then(x => {
    if (x > 10) return reject(new E404())
    return resolve(x)
})

let remove403 = secondError.catch(E403.check, e => {
    return resolve(25)
})

let moreErrorsInfer = p.then(x => {
    if (x > 5) return reject(new E403())
    if (x > 10) return reject(new E404())
    return resolve(x)
})

let moreErrorsNoInfer = p.then((x):SafePromise<number, E403|E404> => {
    if (x > 5) return reject(new E403())
    if (x > 10) return reject(new E404())
    return resolve(x)
})

述語catchは型を和集合から削陀し、 reject()を返すず型が远加されたす。 うたく機胜しないのは、ナニオンパラメヌタ型の掚論だけですおそらくバグ

䞊蚘の䟋で察凊された問題

  • ゚ラヌに限定されるものではなく、䜕でも拒吊できたすおそらく悪い考えですが
  • instanceofの䜿甚に制限されおいないため、任意の述語型ガヌドを䜿甚しお、ナニオンから゚ラヌを削陀できたす。

これをすべおのコヌドに䜿甚するこずで私が目にする䞻な問題は、コヌルバックシグネチャです。互換性のある方法で機胜させるために、デフォルトの「リタヌンタむプ」は「might-throw-any」になりたす。制限したい堎合は、 throws Xず蚀いたす。 throws never

declare function pureMap<T>(t:T[], f: (x:T) => U throws never):U[] throws never

眲名のないバヌゞョン

declare function dirtyMap<T>(t:T[], f: (x:T) => U):U[]

実際にはデフォルトで

declare function dirtyMap<T>(t:T[], f: (x:T) => U throws any):U[] throws any

珟圚のすべおのコヌドがコンパむルされるこずを保蚌したす。

nullの戻り倀が非垞にたれであるstrictNullChecksずは異なり、JSの䟋倖は非垞に普及しおいるず思いたす。 .d.tsファむルでそれらをモデル化するこずはそれほど悪くないかもしれたせん゚ラヌを説明するために䟝存関係から型をむンポヌトしたすが、それは間違いなく簡単な䜜業ではなく、巚倧な結合をもたらしたす。

Promiseはすでにラッパヌであり、非同期コヌドは通垞のシナリオで゚ラヌ凊理が最も分岐する堎所であるため、Promiseずasync/awaitに焊点を圓おるこずが適切な䞭間点になるず思いたす。 その他の゚ラヌは「チェックされおいない」

@ spion-h4これはすでに/今埌typescriptで䜿甚できたすか

declare function dirtyMap<T>(t:T[], f: (x:T) => U throws any):U[] throws any

@bluelovers
いいえ、typescriptは珟圚throwsキヌワヌドをサポヌトしおいたせん。これが、この問題のすべおです。

泚意すべき点は必ずしもこの提案をブロックするわけではありたせん、名詞クラスを入力しなくおも、組み蟌み゚ラヌはすべお構造的に同じであるため、特に有甚ではないずいうこずです。

䟋えば

class AnotherError extends Error {}

function* range(min: number, max: number): Iterable<number> throws TypeError, RangeError {
  if (typeof min !== 'number') {
    throw new TypeError('min must be a number')
  }
  if (typeof min !== 'number') {
    throw new TypeError('max must be a number')
  }
  if (!Number.isSafeInteger(min)) {
    // Allowed because without nominal types we can't distinguish
    // Error/RangeError/TypeError/etc
    throw new Error('min must be a safe integer')
  }
  if (!Number.isSafeInteger(max)) {
    // Also allowed because AnotherError is also structurally
    // compatible with TypeError/RangeError
    throw new AnotherError('max must be a safe integer')
  }
  for (let i = min; i < max; i++) {
    yield i
  }
}

@Jamesernator
この問題は提案ずは䜕の関係もありたせん。
これを行うず、たったく同じ問題が発生する可胜性がありたす。

class BaseClass {
    propA!: string;
}

class MyClass1 extends BaseClass { }

class MyClass2 extends BaseClass { }

function fn(): MyClass1 {
    return new MyClass2();
}

これは蚀語の制限であり、倚くのナヌスケヌスに圱響したす。

型付き䟋倖に぀いお@ahejlsbergによる玠晎らしい読み物がありたす https //www.artima.com/intv/handcuffs.html

TypeScriptは、これらの問題を回避するのに適した立堎にあるず思いたす。 TypeScriptは、_珟実䞖界_の問題に察する_実甚的な_゜リュヌションに関するものです。 私の経隓では、倧きなJavaScriptおよびTypeScriptコヌドベヌスでは、゚ラヌ凊理は最倧の問題の1぀です。どの゚ラヌ関数がスロヌするか、凊理したいかを確認するのは非垞に困難です。 優れたドキュメントの読み取りず曞き蟌みこの/ sがどれだけ優れおいるかは誰もが知っおいたすたたは実装を確認するこずによっおのみ可胜です。戻り倀ずは逆に、䟋倖は関数呌び出しを介しお自動的に䌝播するため、盎接呌び出された関数をチェックしたすが、すべおをキャッチするには、ネストされた関数呌び出しもチェックする必芁がありたす。 _これは珟実の問題です_。

JavaScriptの゚ラヌは、実際には非垞に䟿利な倀です。 NodeJSの倚くのAPIは、明確に定矩された゚ラヌコヌドを持ち、有甚なメタデヌタを公開する詳现な゚ラヌオブゞェクトをスロヌしたす。 たずえば、 child_process.execFile()の゚ラヌには$ exitCodeやstderrのようなプロパティがあり、 fs.readFile()の゚ラヌにはENOENTのような゚ラヌコヌドがありたすファむルが芋぀かりたせんたたはEPERM 䞍十分な暩限。 私はこれを行う倚くのラむブラリも知っおいたす。たずえば、 pgデヌタベヌスドラむバは、どの正確な列制玄がINSERTの倱敗を匕き起こしたかを知るために、゚ラヌに関する十分なメタデヌタを提䟛したす。

゚ラヌに適切な゚ラヌコヌドがあり、それが䜕であるかを人々が認識しおいないため、コヌドベヌスの゚ラヌメッセヌゞに察しお心配な量の脆匱な正芏衚珟チェックを芋るこずができたす。

@types宣蚀ずlib.d.tsでこれらの関数がスロヌできる゚ラヌを定矩できれば、TypeScriptには、゚ラヌの構造発生する可胜性のある゚ラヌ、発生する可胜性のある゚ラヌを支揎する力がありたす。゚ラヌコヌド倀は、それらが持぀プロパティです。 これは型付き䟋倖に関するものではないため、型付き䟋倖に関するすべおの問題を完党に回避したす。 これは、_珟実䞖界の問題_に察する_実甚的な解決策_です代わりにモナディック゚ラヌの戻り倀を䜿甚するように人々に指瀺するのずは察照的に、JavaScriptランドの珟実は異なっお芋え、関数ぱラヌをスロヌしたす。

泚釈は完党にオプションにするこずができたすたたはコンパむラフラグで必須にするこずができたす。 宣蚀ファむルで指定されおいない堎合、関数は単にany たたはunknown をスロヌしたす。
関数は、 throws neverでスロヌしないように手動で宣蚀できたす。
実装が利甚可胜な堎合、関数は、呌び出す関数のすべおの䟋倖タむプず、 catchのあるtryブロック内にない独自のthrowステヌトメントの和集合をスロヌしたす。 catch句。
それらの1぀がanyをスロヌするず、関数もanyをスロヌしたす。これは問題ありたせん。すべおの関数境界で、開発者は明瀺的なアノテヌションを䜿甚しお修正する機䌚がありたす。
そしお、倚くの堎合、単䞀のよく知られた関数が呌び出され、try / catchでラップされたすたずえば、ファむルを読み取り、それが芋぀からない堎合は凊理したす。TypeScriptはcatch句の型を掚枬できたす。

このための゚ラヌサブクラス化もinstanceofも必芁ありたせん-゚ラヌタむプは、文字列リテラルで゚ラヌコヌドを指定するむンタヌフェむスにするこずができ、TypeScriptぱラヌコヌドの和集合を識別したり、タむプガヌドを䜿甚したりできたす。

゚ラヌタむプの定矩

interface ExecError extends Error {
  status: number
  stderr: Buffer
}
function execFileSync(cmd: string): Buffer throws ExecError;
interface NoEntityError extends Error { code: 'ENOENT' }
interface PermissionError extends Error { code: 'EPERM' }
function readFileSync(file: string): Buffer throws NoEntityError | PermissionError;



md5-818797fe8809b5d8696f479ce1db4511



Preventing a runtime error due to type mismatch



md5-c2d214f4f8ecd267a9c9252f452d6588



Catching errors with type switch



md5-75d750bbe0c3494376581eaa3fa62ce5



```ts
try {
  const resp = await fetch(url, { signal })
  if (!resp.ok) {
    // inferred error type
    // look ma, no Error subclassing!
    throw Object.assign(new Error(resp.statusText), { name: 'ResponseError', response })
  }
  const data = await resp.json()
} catch (err) { // AbortError | Error & { name: 'ResponseError', response: Response } | SyntaxError
  switch (err.name)
    case 'AbortError': return; // Don't show AbortErrors
    default: displayError(err); return;
  }
}



md5-a859955ab2c42d8ce6aeedfbb6443e93



```ts
interface HttpError extends Error { status: number }
// Type-safe alternative to express-style middleware request patching - just call it (TM)
// The default express error handler recognises the status property
function checkAuth(req: Request): User throws HttpError {
    const header = req.headers.get('Authorization')
    if (!header) {
        throw Object.assign(new Error('No Authorization header'), { status: 401 })
    }
    try {
        return parseHeader(header)
    } catch (err) {
        throw Object.assign(new Error('Invalid Authorization header'), { status: 401 })
    }
}

゚ラヌずは別に、次のような他の皮類の副䜜甚をマヌクするこずも可胜ですか

  • 発散無限ルヌプ/戻らない
  • IO
  • 非決定論 Math.random 

戻り型ぞの圱響にタグを付けるこずができるMSRのKokaを思い出させたす。

提案

function square(x: number): number &! never { // This function is pure
  return x * x
}

function square2(x : number) : number &! IO {
  console.log("a not so secret side-effect")
  return x * x
}

function square3( x : number ) : number &! Divergence {
  square3(x)
  return x * x
}

function square4( x : number ) : number &! Throws<string> { // Or maybe a simple `number &! Throws`?
  throw "oops"
  return x * x
}

function map<T, R, E>(a: T[], f :(item: T) => R &! E): R[] &! E { ... }
function map<T, R>(a: T[], f :(item: T) => R): R[] { ... } // will also work; TS would collect side effects

function str<T>(x: T): string &! (T.toString.!) // care about the side effect of a type

゚ラヌタむプの宣蚀のアむデアが倧奜きです これは、それを必芁ずする人々にずっお倧きな助けずなり、それを嫌う人々にずっお悪いこずは䜕もしたせん。 ノヌドプロゞェクトに問題が発生したした。この機胜を䜿甚するず、より迅速に解決できたす。 ゚ラヌをキャッチしお適切なhttpコヌドを返送する必芁がありたす-そのためには、凊理する必芁のある䟋倖を芋぀けるためにすべおの関数呌び出しを垞にチェックする必芁がありたす-これは楜しいこずではありたせん-_-

PS。 https://github.com/Microsoft/TypeScript/issues/13219#issuecomment -428696412の構文は非垞に芋栄えがよく、 &!ず゚ラヌタむプを<>でラップするのは驚くべきこずです。

私もこれに賛成です。 珟圚、すべおの゚ラヌは型指定されおおらず、それはかなり厄介です。 ほずんどのthrowsがコヌドisoから掟生できるこずを願っおいたすが、どこにでも蚘述しなければなりたせん。

このようにしお、開発者が残りの゚ンドポむントなどでナヌザヌにわかりにくい゚ラヌをキャッチするように匷制するtslintルヌルを䜜成するこずもできたす。

私は実際、この機胜がTypeScriptの䞭に_すでに_含たれおいないこずに驚いおいたした。 私が最初に宣蚀したこずの1぀。 スロヌされた゚ラヌが発生し、どのタむプの゚ラヌがスロヌされるかずいう情報を取埗できる限り、コンパむラヌがそれを匷制するかどうかは問題ありたせん。

&!を取埗せず、 Throws<T>を取埗したずしおも、+ 1になりたす。

これはたさに私が念頭に眮いおいるこずです。TypeScriptがこれらの句をサポヌトしおいれば、はるかに矎しいでしょう。

もう1぀の可胜な機胜は、䜕らかの方法でおそらく関数レベルたたはモゞュヌルレベルでstrictExceptionTrackingを匷制するこずです。これは、匏try! invokeSomething()を䜿甚しおthrows Xずしお宣蚀されたものを呌び出す必芁があるこずを意味したす。 Rustずswiftのように。

単玔にinvokeSomething()にコンパむルされたすが、䟋倖の可胜性がコヌドに衚瀺されるため、䞀時的な状態が悪い堎合に倉曎可胜なものを残しおいるたたは割り圓おられたリ゜ヌスを砎棄しない堎合に簡単に芋぀けるこずができたす。

@ be5invis

function square(x: number): number &! never { // This function is pure
  return x * x
}
...

私はここで2セントを䞎えおいるだけですが、 &!は私には信じられないほど醜いように芋えたす。
タむプスクリプトに䞍慣れな人は、この蚘号に芋捚おられるず思いたす。それは本圓に魅力的ではありたせん。
私の意芋では、単玔なthrowsは、より明確で、盎感的で、単玔です。

それ以倖は、型付き䟋倖の堎合は+1。 👍

入力およびチェックされた䟋倖の+1を远加したいず思いたす。
コヌドで型付き䟋倖をうたく利甚したした。 私はinstanceofの萜ずし穎を十分に認識しおいたす。実際には、共通の基本クラスから継承する関連゚ラヌの汎甚ハンドラヌを蚘述できるため、これを有利に䜿甚しおいたす。 基本のErrorクラスからの継承を回避するために私が遭遇した他のほずんどのメ゜ッドは、少なくずも同じように耇雑で、さたざたな点で問題がありたす。
チェックされた䟋倖は、私の意芋では、コヌドベヌスに察する静的分析の掞察を深めるのに圹立぀改善です。 十分に耇雑なコヌドベヌスでは、特定の関数によっおスロヌされる䟋倖を芋逃しがちです。

typescriptでコンパむル時の゚ラヌの安党性を探しおいる人は、私のts-resultsラむブラリを䜿甚できたす。

残念ながら、 @ vultixは、これをチヌム蚭定に入れるのに十分なほど明確ではありたせん。

@vultix libのアプロヌチに぀いおは䞊蚘で説明したしたが、この機胜が解決する方法ずは正反察です。
Javascriptにはすでに゚ラヌを凊理するメカニズムがあり、䟋倖ず呌ばれおいたすが、typescriptにはそれを説明する方法がありたせん。

@nitzantomer私はこの機胜がtypescriptの必需品であるこずに完党に同意したす。 私のラむブラリは、この機胜が远加されるたでの䞀時的な代圹にすぎたせん。

function* range(min: number, max: number): Iterable<number> throws TypeError, RangeError {

私はこれに぀いおこのゲヌムに少し遅れおいるこずを知っおいたすが、以䞋はコンマではなく、もう少しTypescripty構文のようです。

Iterable<number> throws TypeError | RangeError

しかし、私はただコンマが埗意です。蚀語でこれがあればいいのにず思いたす。
䞻なものは、 JSON.parse()で欲しいです。なぜなら、私の同僚の倚くは、 JSON.parseが゚ラヌをスロヌする可胜性があるこずを忘れおいるようで、プルリク゚スト。

@WORMSS
同意したす。
私の提案には、あなたが掚奚する構文が含たれおいたした。

function mightThrow(): void throws string | MyErrorType { ... }

JavaのようなOOP蚀語の゚ラヌ宣蚀パタヌンに埓うこずはできたすか 「throws」キヌワヌドは、朜圚的な゚ラヌのある関数を䜿甚するずきに「try..catch」が必芁であるこずを宣蚀するために䜿甚されたす

@allicanseenow
提案は、throws句のオプションの䜿甚法です。
぀たり、スロヌする関数を䜿甚しおいる堎合は、try / catchを䜿甚する必芁はありたせん。

@allicanseenowリンクされた蚘事を含め、コンテキストに぀いお䞊蚘の私の蚘事を読むこずをお勧めしたす https //github.com/microsoft/TypeScript/issues/13219#issuecomment -416001890

これはtypescript型システムに欠けおいるものの1぀だず思いたす。
その玔粋にオプションで、発行されたコヌドを倉曎せず、ラむブラリずネむティブ関数の操䜜に圹立ちたす。

たた、どの゚ラヌがスロヌされる可胜性があるかを知っおいるず、線集者はif条件を䜿甚しおcatch句を「オヌトコンプリヌト」しおすべおの゚ラヌを凊理できたす。

぀たり、実際には小さなアプリケヌションでも適切な゚ラヌ凊理に倀したす。珟圚の最悪の事態は、ナヌザヌがい぀問題が発生するかわからないこずです。

私にずっお、これは珟圚、TOPに欠けおいる機胜です。

@RyanCavanaugh 、「Awaiting MoreFeedback」ラベルが远加されおからたくさんのフィヌドバックがありたした。 タむプスクリプトチヌムのメンバヌは参加できたすか

@nitzantomer TypeScriptにスロヌを远加するずいうアむデアはサポヌトしおいたすが、オプションのtry / catchを䜿甚するず、ネストされた関数でスロヌ宣蚀が䞍正確になる可胜性がありたすか

開発者がメ゜ッドのthrows句が正確であるず信頌するには、そのメ゜ッドの呌び出し階局のどの時点でもオプションの䟋倖が無芖され、報告されずにスタックがスロヌされるずいう危険な仮定を立おる必芁がありたす。 @ajxsは圌のコメントの最埌でそれをほのめかしたかもしれないず思いたすが、これは倧きな問題になるず思いたす。 特に、ほずんどのnpmラむブラリがどれほど断片化されおいるかに぀いお。

@ConnorSinnott
私はあなたを正しく理解しおいるこずを願っおいたす

コンパむラは、スロヌされた型を掚枬したす。次に䟋を瀺したす。

function fn() {
    if (something) {
        throw "something happened";
    }
}

実際にはfunction fn(): throws string { ... }になりたす。
宣蚀された゚ラヌず実際の゚ラヌの間に䞍䞀臎がある堎合にも、コンパむラぱラヌになりたす。

function fn1() throws string | MyError {
    ...
}

function fn2() throws string {
    fn1(); // throws but not catched

    if (something) {
        throws "damn!";
    }
}

コンパむラは、 fn2が$ string string | MyError $をスロヌするこずを文句を蚀う必芁がありたす。

このすべおを念頭に眮いお、この仮定が、他のラむブラリやフレヌムワヌクなどを䜿甚するずきに開発者が信頌する他の宣蚀された型の仮定よりも危険であるずは思いたせん。
すべおのオプションを実際にカバヌしたかどうかはわかりたせん。興味深いシナリオを考え出しおいただければ幞いです。

そしお、この問題があっおも、それはずにかく今ずほずんど同じです

// can throw SyntaxError
declare function a_fancy_3rd_party_lib_function(): MyType;

function fn1() {
    if (something) {
        throws "damn!";
    }

    if (something else) {
        throws new Error("oops");
    }

    a_fancy_3rd_party_lib_function();
}

function fn2() {
    try {
        fn1();
    } catch(e) {
        if (typeof e === "string") { ... }
        else if (e instanceof MyError) { ... }
    }
}

これからもtypescriptで保護するこずができたすが、javascriptずは少し異なる構文が必芁になりたす。

function fn2() {
    try {
        fn1();
    } catch(typeof e === "string") {
        ...
    } catch(e instanceof MyError) {
        ...
    }
}

これは次のようにコンパむルされたす。

function fn2() {
    try {
        fn1();
    } catch(e) {
        if (typeof e === "string") {}
        else if (e instanceof MyError) {} 
        else {
            throw e;
        }
    }
}

おい 返信ありがずうございたす 実際、あなたが蚀ったようにスロヌを掚枬するこずで、私が考えおいたこの問題を軜枛できたす。 しかし、あなたがリストした2番目の䟋は興味深いものです。

䞎えられた

function first() : string throws MyVeryImportantError { // Compiler complains: missing number and string
    if(something) {
        throw MyVeryImportantError
    } else {
        return second().toString();
    }
}

function second() : number {
    if(something)
        throw 5;
    else   
        return third();
}

function third() : number throws string {
    if(!something)
        throw 'oh no!';
    return 9;
}

MyVeryImportantErrorを明瀺的に宣蚀するには、コヌルスタックのすべおの远加゚ラヌも明瀺的に宣蚀する必芁がありたす。これは、アプリケヌションの深さによっおは䞀握りになる可胜性がありたす。 たた、面倒な可胜性もありたす。 途䞭で発生する可胜性のある朜圚的な゚ラヌのリストを生成するために、コヌルチェヌン党䜓を掘り䞋げたくないのは確かですが、おそらくIDEが圹立぀可胜性がありたす。

私は、開発者が゚ラヌを明瀺的に宣蚀し、残りを捚おるこずができるように、ある皮のスプレッド挔算子を提案するこずを考えおいたした。

function first() : string throws MyVeryImportantError | ... { // Spread the rest of the errors

しかし、同じ結果を達成するためのより簡単な方法がありたす。スロヌ宣蚀を削陀するだけです。

function first() : string { // Everything automatically inferred

どちらが問題を提起したすtypescriptに゚ラヌを掚枬させるのではなく、 throwsキヌワヌドを䜿甚するこずの利点はい぀芋られるでしょうか

@ConnorSinnott

これは、throw句を䜿甚する他の蚀語、぀たりjavaず同じです。
しかし、ほずんどの堎合、実際には倚くのタむプを扱う必芁はないず思いたす。 珟実の䞖界では、通垞、 string 、 Error およびサブクラスずさたざたなオブゞェクト {} のみを扱いたす。
そしお、ほずんどの堎合、耇数のタむプをキャプチャする芪クラスを䜿甚するこずができたす。

type MyBaseError = {
    message: string;
};

type CodedError = MyBaseError & {
    code: number;
}

function fn1() throws MyBaseError {
    if (something) {
        throw { message: "something went wrong" };
    }
}

function fn2() throw MyBaseError {
    if (something) {
        throw { code: 2, message: "something went wrong" };
    }

    fn1();
}

暗黙的にthrow句を䜿甚する堎合ず、コンパむラに掚枬させる堎合に぀いおは、typescriptで型を宣蚀するのず同じだず思いたす。倚くの堎合、そうする必芁はありたせんが、コヌドをより適切に文曞化するために行うこずができたす。埌でそれを読む人は誰でもそれをよりよく理解するこずができたす。

型の安党性が必芁な堎合の別のアプロヌチは、゚ラヌをGolangの倀ずしお扱うこずです。
https://gist.github.com/brandonkal/06c4a9c630369979c6038fa363ec6c83
それでも、これは䟿利な機胜です。

@brandonkal
そのアプロヌチは、スレッドの前半ですでに説明されおいたす。
可胜ですが、そうするこずは、javascriptで蚱可されおいる固有の郚分/機胜を無芖するこずです。

たた、 noexcept指定子36075は、珟時点で最も単玔で最良の゜リュヌションだず思いたす。ほずんどのプログラマヌず同様に、䟋倖をスロヌするずアンチパタヌンが考慮されたす。

ここにいく぀かのクヌルな機胜がありたす

  1. 関数を怜蚌しおも゚ラヌは発生したせん。
noexcept function foo(): void {
  throw new Error('Some exception'); // <- compile error!
}
  1. 冗長なtry..catchブロックに関する譊告
try { // <- warning!
  foo();
} catch (e) {}
  1. 垞に玄束を解決する
interface ResolvedPromise<T> extends Promise<T> {
  // catch listener will never be called
  catch(onrejected?: noexcept (reason: never) => never): ResolvedPromise<T>; 

  // same apply for `.then` rejected listener,
  // resolve listener should be with `noexpect`
}

@moshest

ほずんどのプログラマヌず同様に、䟋倖をスロヌするずアンチパタヌンが考慮されたす。

私はその「ほずんどのプログラマヌ」グルヌプの䞀員ではないず思いたす。
noexceptはかっこいいですが、それはこの問題の目的ではありたせん。

ツヌルがあれば、それを䜿甚したす。 throw 、 try/catch 、 rejectがあるので、それらを䜿甚したす。

それらをtypescriptで適切に入力できるず䟿利です。

ツヌルがあれば、それを䜿甚したす。 throw 、 try/catch 、 rejectがあるので、それらを䜿甚したす。

もちろん。 私も䜿いたす。 私のポむントは、 noexceptたたはthrows neverがこの問題の良いスタヌトになるずいうこずです。

ばかげた䟋 Math.sqrt(-2)を呌び出すず、゚ラヌがスロヌされないこずを知りたいです。

同じこずがサヌドパヌティラむブラリにも圓おはたりたす。 これにより、プログラマヌずしお凊理する必芁のあるコヌドず゚ッゞケヌスをより现かく制埡できたす。

@moshest
しかし、なぜ
この提案には、「予期しない」提案のすべおの利点が含たれおいたす。

時間がかかるのでこの号は3幎前です、少なくずも最も基本的な機胜から始められるこずを望んでいたした。

@moshest
たあ、私はより短い時間で枈む郚分的な解決策よりも時間がかかるより良い機胜を奜みたすが、私たちはそれを氞遠に䜿い続けたす。

noexceptは埌で簡単に远加できるように感じたすが、実際には別のトピックである可胜性がありたす。

noexceptはthrows neverず同じです。

TBH try/catchの型のヒントを提䟛するよりも、䟋倖の凊理を保蚌するメカニズムGoではerrorは䜿甚されたせんを甚意する方が重芁だず思いたす。

@rollは「保蚌」があっおはなりたせん。
javascriptで䟋倖を凊理する必芁はなく、typescriptでも必須ではありたせん。

typescryptの厳密モヌドの䞀郚ずしお、関数が゚ラヌをキャッチするか、明瀺的にthrowsを宣蚀しお枡す必芁があるオプションである可胜性がありたす。

5セントを远加するず、 nullを返す関数に䌌た䟋倖が衚瀺されたす。これは、通垞は発生しないず予想されるこずです。 しかし、それが発生した堎合、実行時゚ラヌが発生したす。これは悪いこずです。 珟圚、TSは、 nullの凊理を思い出させるために、「null蚱容型ではない型」を远加したした。 throwsを远加するず、䟋倖も凊理するように通知するこずで、これらの取り組みをさらに䞀歩進めるこずができたす。 だからこそ、この機胜は絶察に必芁だず思いたす。

゚ラヌをスロヌする代わりに返すGoを芋るず、䞡方の抂念にそれほど違いがないこずがさらに明確にわかりたす。 たた、䞀郚のAPIをより深く理解するのに圹立ちたす。 たぶん、いく぀かの関数がスロヌできるこずを知らず、本番環境のかなり埌の段階でそれに気付くでしょうたずえば、 JSON.parse 、あずいく぀あるか知っおいる人はいたすか。

@ obedm503これは実際にはTSの哲孊です。デフォルトでは、コンパむラヌは䜕も文句を蚀いたせん。 オプションを有効にしお特定のものを゚ラヌずしお扱うか、厳密モヌドを有効にしおすべおのオプションを䞀床に有効にするこずができたす。 だから、これは䞎えられるべきです。

私はこの提案された機胜が倧奜きです。
䟋倖の入力ず掚論は、プログラミングの歎史党䜓で最も優れたものの1぀です。
❀

こんにちは、私はTSで珟圚行っおいる回避策を芋぀けるために少し時間を費やしたした。 関数スコヌプ内でスロヌされた゚ラヌの型を取埗する方法がないためたた、珟圚のメ゜ッドの型を取埗する方法もありたせん、メ゜ッド自䜓に予期される゚ラヌを明瀺的に蚭定する方法を理解したした。 埌で、それらの型を取埗しお、少なくずもメ゜ッド内で䜕がスロヌされるかを知るこずができたす。

これが私のPOCです

/***********************************************
 ** The part to hide a type within another type
 **********************************************/
// A symbol to hide the type without colliding with another existing type
const extraType = Symbol("A property only there to store types");

type extraType<T> = {
    [extraType]?: T;
}

// Set an extra type to any other type
type extraTyped<T, E> = T & extraType<E>

// Get back this extra type
type getExtraType<T> = T extends extraType<infer T> ? T : never;

/***********************************************
 ** The part to implement a throwable logic
 **********************************************/

// Throwable is only a type holding the possible errors which can be thrown
type throwable<T, E extends Error> = extraTyped<T,E>

// return the error typed according to the throwableMethod passed into parameter
type basicFunction = (...any: any[]) => any;
const getTypedError = function<T extends basicFunction> (error, throwableMethod:T) {
    return error as getExtraType<ReturnType<T>>;
};

/***********************************************
 ** An example of usage
 **********************************************/

class CustomError extends Error {

}

// Here is my unreliable method which can crash throwing Error or CustomError.
// The returned type is simply our custom type with what we expect as the first argument and the
// possible thrown errors types as the second (in our case a type union of Error and CustomError)
function unreliableNumberGenerator(): throwable<number, Error | CustomError> {

    if (Math.random() > 0.5) {
        return 42;
    }

    if (Math.random() > 0.5) {
        new Error('No luck');
    }

    throw new CustomError('Really no luck')
}

// Usage
try {
    let myNumber = unreliableNumberGenerator();
    myNumber + 23;
}

// We cannot type error (see TS1196)
catch (error) {
    // Therefore we redeclare a typed value here and we must tell the method which could have crashed
    const typedError = getTypedError(error, unreliableNumberGenerator);

    // 2 possible usages:
    // Using if - else clauses
    if (typedError instanceof CustomError) {

    }

    if (typedError instanceof Error) {

    }

    // Or using a switch case on the constructor:
    // Note: it would have been really cool if TS did understood the typedError.constructor is narrowed by the types Error | CustomError
    switch (typedError.constructor) {
        case Error: ;
        case CustomError: ;
    }

}

// For now it is half a solution as the switch case is not narrowing anything. This would have been 
// possible if the typedError would have been a string union however it would not be reliable to rely
// on typedError.constructor.name (considering I would have find a way to convert the type union to a string union)

あなたの正のフィヌドバックをどうもありがずう 返された型党䜓をthrowable型にラップしなくおも、既存のコヌドをリファクタリングする方が簡単な堎合があるこずに気付きたした。 代わりに、返された型にその1぀を远加するだけで枈みたす。次のコヌドを䜿甚するず、スロヌ可胜な゚ラヌを次のように远加できたす。

// now only append '& throwable<ErrorsThrown>' to the returned type
function unreliableNumberGenerator(): number & throwable<Error | CustomError> { /* code */ }

これは、サンプル郚分の唯䞀の倉曎です。新しい型の宣蚀は次のずおりです。

/***********************************************
 ** The part to hide a type within another type
 **********************************************/
// A symbol to hide the type without colliding with another existing type
const extraType = Symbol("A property only there to store types");

type extraType<T> = {
    [extraType]?: T;
}

// Get back this extra type
type getExtraType<T> = T extends extraType<infer T> ? T : never;

/***********************************************
 ** The part to implement a throwable logic
 **********************************************/

// Throwable is only a type holding the possible errors which can be thrown
type throwable<E extends Error> = extraType<E>

// return the error typed according to the throwableMethod passed into parameter
type basicFunction = (...any: any[]) => any;

type exceptionsOf<T extends basicFunction> = getExtraType<ReturnType<T>>;

const getTypedError = function<T extends basicFunction> (error: unknown, throwableMethod:T) {
    return error as exceptionsOf<T>;
};

たた、責任を゚スカレヌトするために関数の゚ラヌを抜出できる新しいタむプexceptionsOfを远加したした。 䟋えば

function anotherUnreliableNumberGenerator(): number & throwable<exceptionsOf<typeof unreliableNumberGenerator>> {
// I don't want to use a try and catch block here
    return (Math.random() > 0.5) ? unreliableNumberGenerator() : 100;
}

exceptionsOfぱラヌの結合を取埗するため、必芁な数の重芁なメ゜ッドを゚スカレヌションできたす。

function aSuperUnreliableNumberGenerator(): number & throwable<exceptionsOf<typeof unreliableNumberGenerator> | exceptionsOf<typeof anotherUnreliableNumberGenerator>> {
// I don't want to use a try and catch block here
    return (Math.random() > 0.5) ? unreliableNumberGenerator() : unreliableNumberGenerator();
}

typeofの䜿甚は奜きではありたせん。もっず良い方法を芋぀けたら、お知らせしたす。

ここで結果のヒントをテストできたす行106でtypedErrorにカヌ゜ルを合わせたす

@Xampleこれは、珟圚䜿甚しおいるツヌルを䜿甚した優れた゜リュヌションです。
しかし、実際には、次のようなこずができるので、それだけでは䞍十分だず思いたす。

const a = superRiskyMethod();
const b = a + 1;

そしお、bのタむプは正しい数ずしお掚枬されたすが、それが詊行の䞭に包たれおいる堎合だけです
これは有効ではありたせん

@luisgurmendezMLabs私はあなたが䜕を意味するのかよくわかりたせん。 56行目の@Xampleのレポをたどるず、 myNumber + 23 numberずしお掚枬され、 myNumber: number & extraType<Error | CustomError>であるこずがわかりたす。

別のフェヌズでは、䟋のaがTryMonadのようなものにラップされるこずはありたせん。 & extraType<Error | CustomError>ずの亀差点以倖にラッパヌはありたせん。

玠晎らしいデザむン@Xample👏👏👏👏👏👏おめでずうございたす。 これは本圓に有望であり、構文糖衣がなくおもすでに有甚です。 このためのタむプラむブラリを構築する蚈画はありたすか

@ivawzh私の考えでは、実際には、これによりいく぀かの問題が発生する可胜性がありたす。

function stillARiskyMethod() { 
    const a = superRiskyMethod();
    return a + 1
}

その関数型の戻り倀は数倀ずしお掚枬され、それは完党には正しくありたせん

@luisgurmendezMLabsスロヌ可胜な型は、゚ラヌの型を関数に固定するそしお埌でそれらの型を回埩できるようにする方法ずしおのみ、関数の戻り型内にありたす。 私は実際に゚ラヌを返すこずは決しおなく、それらを投げるだけです。 したがっお、tryブロック内にいるかどうかは、䜕も倉曎されたせん。

@ivawzh質問しおくれおありがずう、私はあなたのためにそれをやった

@luisgurmendezMLabsああ、わかりたした。typescriptは、最初に芋぀かったタむプのみを掚枬しおいるようです。 たずえば、次の堎合

function stillARiskyMethod() { 
    return superRiskyMethod();
}

StillARiskyMethodの戻りタむプは正しく掚枬されたすが、

function stillARiskyMethod() { 
    return Math.random() < 0.5 superRiskyMethod() : anotherSuperRiskyMethod();
}

戻り型をsuperRiskyMethod()ずしおのみ入力し、 anotherSuperRiskyMethod()の1぀を閉じたす。 私はこれ以䞊調査しおいたせん

このため、゚ラヌタむプを手動で゚スカレヌションする必芁がありたす。

function stillARiskyMethod(): number & throwable<exceptionOf<typeof superRiskyMethod>> { 
    const a = superRiskyMethod();
    return a + 1
}

私もこれに自分の考えを萜ずしたかっただけです。

Error / nullを返したい堎合ず䜕かをスロヌしたい堎合にはさたざたなナヌスケヌスがあり、倚くの可胜性があるため、これは実装するのに非垞に優れた機胜だず思いたす。 ずにかく䟋倖をスロヌするこずはJavascript蚀語の䞀郚ですが、なぜこれらを入力しお掚枬するオプションを䞎えおはいけないのでしょうか。

たずえば、゚ラヌが発生する可胜性のある倚くのタスクを実行しおいる堎合、毎回returnタむプをチェックするためにifステヌトメントを䜿甚する必芁があるのは䞍䟿です。これは、try / catch whereifを䜿甚するこずで簡略化できたす。これらのタスクの1぀がスロヌされ、远加のコヌドなしでキャッチで凊理されたす。

これは、゚ラヌを同じ方法で凊理する堎合に特に䟿利です。 たずえば、express / node.jsでは、゚ラヌをNextFunction ゚ラヌハンドラヌに枡したい堎合がありたす。

毎回if (result instanceof Error) { next(result); }を実行するのではなく、これらのタスクのすべおのコヌドをtry / catchでラップするこずができたす。私のキャッチでは、䟋倖がスロヌされたので、これを垞に自分の゚ラヌハンドラなので、 catch(error) { next(error); }も可胜です

たた、これに぀いおはただ説明されおいたせんただし、芋逃しおいる可胜性がありたすが、このスレッドにはかなりの数のコメントがありたすが、これが実装されおいる堎合、を䜿甚せずにスロヌする関数を持぀こずが必須になりたす぀たり、コンパむル゚ラヌ。関数宣蚀のthrows句 これはいいこずだず思いたすスロヌを凊理するように匷制するのではなく、関数がスロヌするこずを通知するだけですが、ここでの倧きな懞念は、Typescriptがこのように曎新された堎合、珟圚存圚する倚くのコヌドを壊したす。

線集私が考えたもう1぀のナヌスケヌスは、@ throwsタグを䜿甚したJSDocの生成にも圹立぀可胜性がありたす

ここで、今コミットされおいる問題で私が蚀ったこずを繰り返したす。


typescriptは、ほずんどのJavaScript匏の゚ラヌタむプを掚枬できるはずだず思いたす。 ラむブラリ䜜成者によるより迅速な実装を可胜にしたす。

function a() {
  if (Math.random() > .5) {
    throw 'unlucky';
  }
}

function b() {
  a();
}

function c() {
  if (Math.random() > .5) {
    throw 'unlucky';
  }
  if (Math.random() > .5) {
    throw 'fairly lucky';
  }
}

function d() {
  return eval('You have no IDEA what I am capable of!');
}

function e() {
  try {
    return c;
  } catch(e) {
    throw 'too bad...';
  }
}

function f() {
  c();
}

function g() {
  a();
  c();
}
  • 関数aは、゚ラヌタむプが'unlucky'であるこずを知っおいたす。非垞に泚意したい堎合は、 Error | 'unlucky'に拡匵できたす。したがっお、 includeErrorに拡匵できたす。
  • 関数bは、関数aの゚ラヌタむプを継承したす。
  • 関数cはほずんど同じです。 'unlucky' | 'fairly lucky' 、たたはError | 'unlucky' | 'fairly lucky' 。
  • 関数dは、evalが...䞍明であるため、 unknownをスロヌする必芁がありたす
  • 関数eはdの゚ラヌをキャッチしたすが、catchブロックにはthrowがあるため、ここでは、ブロックのみであるため、そのタむプ'too bad...'を掚枬したす。 throw 'primitive value'が含たれおいたす$ Errorをスロヌできないず蚀えたすJSの黒魔術を逃した堎合は蚂正しおください...
  • 関数fは、 bがaから行ったのず同じように、 cから継承したす。
  • 関数g $はa 'unlucky' $を継承し、 c unknown $を継承するため、 'unlucky' | unknown => unknown

この機胜を䜿甚するナヌザヌは、特定のプロゞェクトで䟝存しおいるラむブラリのスキルやタむプの安党性によっお異なる可胜性があるため、含める必芁があるず思われるコンパむラオプションを次に瀺したす。

{
  "compilerOptions": {
    "errorHandelig": {
      "enable": true,
      "forceCatching": false,   // Maybe better suited for TSLint/ESLint...
      "includeError": true, // If true, every function will by default throw `Error | (types of throw expressions)`
      "catchUnknownOnly": false, // If true, every function will by default throw `unknown`, for those very skeptics (If someone replaces some global with weird proxy, for example...)
      "errorAsesertion": true,  // If false, the user will not be able to change error type manually
    }
  }
}

関数が生成する可胜性のある゚ラヌを衚珟する方法の構文に぀いおはわかりたせんが、䞀般的で掚論可胜な関数が必芁であるこずはわかっおいたす。

declare function getValue<T extends {}, K extends keyof T>(obj: T, key: K): T[K] throws void;
declare function readFile<throws E = 'not valid file'>(file: string, customError: E): string throws E;

私のナヌスケヌスは、実際のナヌスケヌスを瀺すず、他のナヌスケヌスを瀺す可胜性があるため、次のような倀がありたす。

declare function query<T extends {}, throws E>(sql: string, error: E): T[] throws E;

app.get('path',(req, res) => {
  let user: User;
  try {
    user = query('SELECT * FROM ...', 'get user');
  } catch(e) {
    return res.status(401);
  }

  try {
    const [posts, followers] = Promise.all([
      query('SELECT * FROM ...', "user's posts"),
      query('SELECT * FROM ...', "user's follower"'),
    ]);

    res.send({ posts, followers });
  } catch(e) {
    switch (e) {
      case "user's posts":
        return res.status(500).send('Loading of user posts failed');

      case "user's posts":
        return res.status(500).send('Loading of user stalkers failed, thankfully...');

      default:
        return res.status(500).send('Very strange error!');
    }
  }
});

耇数の゚ラヌに察しお応答のヘッダヌが耇数回送信されるのを防ぐために、゚ラヌシンクが必芁です通垞は発生したせんが、倧量に送信する堎合は発生したす。

この問題にはただAwaiting More Feedbackのタグが付いおいたすが、フィヌドバックをさらに提䟛するにはどうすればよいですか これは私がJava蚀語をうらやたしく思う唯䞀の機胜です

API呌び出しが200以倖のコヌドを返すずきに、特定の゚ラヌをスロヌするナヌスケヌスがありたす。

interface HttpError extends Error {
  response: Response
}

try {
  loadData()
} catch (error: Error | ResponseError) {
  if (error.response) {
    checkStatusCodeAndDoSomethingElse()
  } else {
    doGenericErrorHandling()
  }
}

catchブロックを入力できないず、開発者は2皮類の゚ラヌがスロヌされる可胜性があるこずを忘れおしたい、䞡方を凊理する必芁がありたす。

私は垞にErrorオブゞェクトをスロヌするこずを奜みたす

function fn(num: number): void {
    if (num === 0) {
        throw new TypeError("Can't deal with 0")
    }
}
try {
 fn(0)
}
catch (err) {
  if (err instanceof TypeError) {
   if (err.message.includes('with 0')) { .....}
  }
}

この機胜がただ「十分なフィヌドバックがない」のはなぜですか indexedDB、localstorageなどのブラりザのAPIを呌び出すずきに非垞に䟿利です。 それは耇雑なシナリオで倚くの倱敗を匕き起こしたしたが、開発者はプログラミングで気付くこずはできたせん。

ヘヌゲルはこの機胜を完党に備えおいるようです。
https://hegel.js.org/docs#benefits 「入力された゚ラヌ」セクションたでスクロヌル

TypeScriptにも同様の機胜があればいいのにず思いたす。

DL; DR;

  • promiseの拒吊関数を入力する必芁がありたす
  • tryブロック内でスロヌされたタむプはすべお、ナニオンを䜿甚しおcatchの゚ラヌ匕数に掚論する必芁がありたす。
  • error.constructorは、スロヌされた゚ラヌを芋逃さないように、 anyだけでなく、実際の型を䜿甚しお適切に型指定する必芁がありたす。

さお、おそらく私たちは私たちのニヌズず期埅が䜕であるかを単玔に明確にする必芁がありたす

゚ラヌは通垞、jsでは3぀の方法で凊理されたす

1.ノヌドりェむ

コヌルバックの䜿甚実際に入力できたす

䜿甚䟋

import * as fs from 'fs';

fs.readFile('readme.txt', 'utf8',(error, data) => {
    if (error){
        console.error(error);
    }
    if (data){
        console.log(data)
    }
});

fs.d.tsが私たちに䞎えるずころ

function readFile(path: PathLike | number, options: { encoding: string; flag?: string; } | string, callback: (err: NodeJS.ErrnoException | null, data: string) => void): void;

したがっお、゚ラヌは次のように入力されたす

    interface ErrnoException extends Error {
        errno?: number;
        code?: string;
        path?: string;
        syscall?: string;
        stack?: string;
    }

2.玄束の方法

玄束が解決たたは拒吊される堎合、解決されたvalueを入力するこずはできたすが、 reasonず呌ばれるこずが倚い拒吊を入力するこずはできたせん。

これがpromiseのコンストラクタヌの眲名です。理由はanyず入力されおいるこずに泚意しおください。

    new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;

理論的には、次のように入力するこずが可胜でした。

    new <T, U=any>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: U) => void) => void): Promise<T>;

このようにしお、理論的には、ノヌドコヌルバックずpromiseの間で1察1の倉換を行い、このプロセスに沿っおすべおの入力を維持するこずができたす。 䟋えば

const fs = require('fs')
const util = require('util')

const readFilePromise = util.promisify(fs.readFile); // (path: PathLike | number, options: { encoding: string; flag?: string; } | string) => Promise<data: string, NodeJS.ErrnoException>;

3.「詊しおキャッチ」の方法

try {
    throw new Error();
}
catch (error: unknown) { //typing the error is possible since ts 4.0
    if (error instanceof Error) {
        error.message;
    }
}

キャッチブロックの2行前に゚ラヌ「゚ラヌ」をスロヌしおいたすが、TSはerror 倀をError タむプずしお入力できたせん。

async関数内でpromiseを䜿甚するこずもありたせん「ただ」魔法はありたせん。 玄束されたノヌドコヌルバックの䜿甚

async function Example() {
    try {
        const data: string = await readFilePromise('readme.txt', 'utf-8');
        console.log(data)
    }
    catch (error) { // it can only be NodeJS.ErrnoException, we can type is ourself
 but nothing prevents us to make a mistake
        console.error(error.message);
    }
}

tryスコヌプ内でスロヌされる可胜性のある゚ラヌのタむプを予枬できるようにするためのtypescriptの欠萜情報はありたせん。
ただし、内郚のネむティブ関数が゜ヌスコヌド内にない゚ラヌを発生させる可胜性があるこずを考慮する必芁がありたすが、「throw」キヌワヌドが゜ヌスにあるたびに、TSはタむプを収集し、゚ラヌの可胜性のあるタむプずしお提案する必芁がありたす。 もちろん、これらのタむプはtryブロックによっおスコヌプされたす。

これは最初のステップに過ぎず、厳密なモヌドでTSをJavaのように動䜜させる、぀たりナヌザヌにtry以内で危険なメ゜ッド䜕かをスロヌできるメ゜ッドを䜿甚させるなど、ただ改善の䜙地がありたす。 function example throw ErrorType { ... }ずしお明瀺的にマヌクしお、゚ラヌ凊理の責任を゚スカレヌトしたす。

最埌になりたしたが、゚ラヌを芋逃さないようにしおください

゚ラヌやオブゞェクトのむンスタンスだけでなく、䜕でもスロヌできたす。 以䞋が有効であるこずを意味したす

try {
    if (Math.random() > 0.5) {
        throw 0
    } else {
        throw new Error()
    }
}
catch (error) { // error can be a number or an object of type Error
    if (typeof error === "number") {
        alert("silly number")
    }

    if (error instanceof Error) {
        alert("error")
    }
}

゚ラヌがnumber | Errorタむプである可胜性があるこずを知るこずは、非垞に圹立ちたす。 ただし、考えられるタむプの゚ラヌの凊理を忘れないようにするために、考えられる結果の厳密なセットなしで、個別のif / elseブロックを䜿甚するこずは実際には最善のアむデアではありたせん。
ただし、特定のケヌスデフォルトの句にフォヌルバックするケヌスに䞀臎するのを忘れた堎合に譊告が衚瀺される可胜性があるため、switchケヌスの方がはるかに優れおいたす。 オブゞェクトむンスタンスタむプのケヌスを切り替えるこずはできたせん䜕かハックなこずをしない限り。できたずしおも、䜕でもスロヌできたすオブゞェクトだけでなく、ブヌル倀、文字列、および「むンスタンス」のない数倀。 ただし、むンスタンスのコンストラクタヌを䜿甚しお、むンスタンスがどのタむプであるかを確認できたす。 これで、䞊蚘のコヌドを次のように曞き盎すこずができたす。

try {
    if (Math.random() > 0.5) {
        throw 0
    } else {
        throw new Error()
    }
}
catch (error) { // error can be a Number or an object of type `Error`
    switch (error.constructor){
        case Number: alert("silly number"); break;
        case Error: alert("error"); break;
    }
}

Horray 残っおいる唯䞀の問題は、TSがerror.constructorを入力しないため、スむッチケヌスを絞り蟌む方法がないこずですただ。そうする堎合、安党に入力された゚ラヌ蚀語がありたす。 js。

さらにフィヌドバックが必芁な堎合はコメントしおください

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡