web-dev-qa-db-ja.com

演算子「==」は、TypeScript 2のタイプxおよびyに適用できません

TypeScriptバージョン:2.0.2.0

コード私はコードが少し愚かであることを知っていますが、実際にはコードにこれらの種類のテストがあり(式ビジターを作る)、私は本当にこれらを考えていますすぐに飛んでコンパイルする必要があります。

var a: boolean = (true == false);
var b: boolean = (5 == 2);

代わりに、オペランドequalをタイプ 'true'、 'false'、 '5'および '2'に適用できないと文句を言います。それらがブール値でも数値でもないことをマークしてください。実際には「true」、「false」、「5」、「2」のタイプです。タイプ「string」と「boolean」は比較できないことを知っていますが、ちょっと、5は実際には数字であり、タイプ「5」ではなく、私は間違っていますか?

ただし、これはコンパイルされます。

let x = 2;
var a: boolean = 5 == x;
var b: boolean = <number>5 == <number>2;

私は何かを逃していますか、なぜ5と2がタイプ「番号」と見なされないのですか?

期待される動作:コンパイルする必要があります

実際の動作: 'Operand' == 'は型' <first argument> 'および' <second argument>に適用できないというコンパイルエラーが発生します'

背景TypeScriptでこのような問題があることを定義しましたが、どうしてですか? https://github.com/Microsoft/TypeScript/issues/6167

28
Lostfields

リテラル型には多くの利点があります。コンパイラにより型をできるだけ狭くできるためです。ユースケースはめったに出てきませんが、型をできるだけ狭くしたい場合は、言語の設計全体に浸透します。確かに、この特定のケースではあなたの人生が難しくなりますが、言語全体としては理にかなっています。このまれなユースケースをサポートするために、ユーザーは著しく悪い言語に苦しむ必要があります。

残念ながら、2番目の例で提案する明示的な型指定を使用する必要があります。大部分のユーザーwantsがこれを行おうとすると叫ぶ言語であるため、これが修正されることはありません。これはおそらく、大多数の場合のバグの兆候です。

9
Simon Meskens

なぜ5と2がタイプ「番号」とみなされないのですか

リテラル型は5および2。例えば.

var x: 5; 
// can only ever be assigned to 5 
x = 5; // okay 
x = 2; // Error 

エラーにならないようにするための実際のユースケースは見当たりません。これは、あなたを助けようとしている単なるコンパイラです。十分な動機が見られたら、問題を作成してください。

10
basarat

Erlang開発者として、私はErlangでこの種のエラーを見てきましたが、TypeScriptでそれが何を意味するのか確信が持てなかったので、問題を理解するのに役立つ例を次に示します。

_let answer: "yes" | "no" | "maybe" = "yes";
if (Math.random() > 0.5) {
    answer = "maybe";
}

if (answer === "yes") {
    console.log('yes');
}

if (answer === "no") {
    console.log('no');
}
_

エラーでコンパイルされません:

_error TS2365: Operator '===' cannot be applied to types '"yes" | "maybe"' and '"no"'.
_

まず、ここに解決策

_let answer = "yes" as "yes" | "no" | "maybe";
_

今の説明:

このコードは非常に単純であり、コンパイル時に理解できるため、TypeScriptはanswerが_"no"_になる可能性のあるコードの場所がないことを知っているので、(非常に不可解な形式ではありますが)その答えは常に「ノー」ではないので、文字通り、それがチェックされる理由はありません。しかし(Erlangのように)これは、answerを_"no"_にするデバッグ用のコードをコメントアウトすることを決めたときなど、非常に明白な理由で発生する可能性があります。ここで_let answer = "yes" as "yes" | "no" | "maybe";_またはlet answer = <("yes" | "no" | "maybe")>"yes";を使用すると、コードに表示されなくても、「yes」は「no」になり得るとTypeScriptに認識させます。したがって、一時的に削除されたコードの場合、2番目の解決策があります。

_if (0) {
    answer = "no";
}
_

この条件は決して真ではありませんが、TypeScriptコンパイラが真であると考えるのに十分な「複雑」です。私のErlangのアプローチは_when X and not X_を使用することです。これはif (x && !x) {になりますが、少なくとも2.4では、数値式を使用できます。

しかし、ある時点でコンパイラが正しい場合、solutionは_"no"_のチェックを削除します:)

そのため、OPの質問に戻り、コードをコンパイルするには、次のように変更する必要があります。

_var a = false;
var b = false;
_

コンパイラがそれを知っていれば、おそらくあなたもそれを知っていたでしょう。

4
JLarky

次のようなシナリオで同じ問題に直面しました。

let a: string;

a === 'some-value1' && a === 'some-value2';  // <==

2行目も同じエラーを生成します。TypeScriptはsmartであるため、特定の時点の文字列型に2つ(またはそれ以上)の異なる文字列リテラルを含めることはできません。

上記の式の正しいアプローチは、式でORを使用することです。

a === 'some-value1' || a === 'some-value2';  // works fine :)