へのリンクあなたは直接コンパイラがParent
インスタンスが本当にChild
であることを知る方法がないという理由だけでChild
にParent
をキャストすることはできません。代わりに、キャストの型ガードを使用してください:警備if
コンパイラ内部
class Parent {
prop: string|null = null;
isChild(): this is Child {
return (this as any).otherProp !== undefined;
}
}
class Child extends Parent
{
otherProp: string|null = null;
}
function test(p: Parent) {
if (p.isChild()) {
console.log(p.otherProp);
}
}
は今それp
はまだちょうどParent
ある外p
は、Child
であることを知っています。
またはより良いまだ、サブクラスでガードをオーバーライドして、あなたはまったく型キャストを行うことを避けることができます。
class Parent {
prop: string|null = null;
isChild(): this is Child {
return false;
}
}
class Child extends Parent
{
otherProp: string|null = null;
isChild(): this is Child { return true; }
}
function test(p: Parent) {
if (p.isChild()) {
console.log(p.otherProp);
}
}
あなたが、私はこれはバグか意図的であるかどうかを疑問に答えていないことが適切ですTypescriptの著者の側では、私の推測では、可能性のあるエラーをキャッチしようとしているのですが、確認または拒否するこの正確な動作の説明を見つけることはできませんでした。あなたがあなたの元のコードの作業を行うことができます
もう一つの方法は、明示的castToChild
方法でthis
の種類を活字体伝えることです:
class Parent {
prop: string|null = null;
castToChild(this: Parent): Child{
return this as Child;
}
}
class Child extends Parent
{
otherProp: string|null = null;
}
function foo() {
let p: Parent = new Child();
let c = p.castToChild();
console.log(c.otherProp);
}
これはまだ実際にはダブルキャストをやっているが、おそらく少しクリーナーを探します。しかし、明示的なthis
パラメータthis
はタイプParent
ですが、キャスト可能な明示的なパラメータを使用して直接キャストできないため、動作の不思議さが表示されます。
申し訳ありませんが、私はあなたの解決策があまりにも複雑であると感じています。中間変数を持つ、またはダブルキャストを使用することで私の回避策ははるかに短く、追加のコードを必要としません。しかし、それらは不要な構文的ノイズを生成します。私はコンパイラが親が実際に子どもであることを知らないことに同意しますが、これが正確に私がキャスティングを行う理由です。 –
面白い意見。確かにtypescriptを使うのは、あなたが間違っているとコンパイラがあなたに知らせることができないことがあるからです。あなたはいつもjavascriptを使わず、これらの型について全く心配する必要がないので、コンパイラよりもよく分かっているのですか? – Duncan
私の答えが何とかあなたを怒らせてしまったのであれば申し訳ありませんが、確かに私の意図ではありませんでした。しかし、あなたの提案は私の質問ではまだ答えではありません: "TS-コンパイラがキャストを二重キャストとして受け入れるか中間変数を使うのはなぜですか? 1つではなく2つのステップを使用して同じ方法を実行することは、私が「構文的ノイズ」と呼んだものです。 –