2016-12-09 9 views
1

抽象クラスで抽象メソッドを記述することはできません。numberまたはstringをとり、数値または文字列を返すことはできません。 私は|シンボルを使用して、メソッドに引数があり、戻り値の型が文字列ごとに異なることを伝えています。
次に、抽象クラスaから拡張され、引数をオーバーライドしようとする2つのクラスbcを作成します。
次に、変数xを宣言していますが、どのタイプがbクラスまたはcクラスに似ている可能性があります。ランダムステートメントに応じてこれらのクラスのインスタンスを作成しています。
最後に私はtest()メソッドを呼び出そうとしていますが、TSコンパイラは私に以下のエラーを与えています。ここでメソッドの引数と戻り値の型はtypescriptでオーバーライドされます

abstract class a { 
    abstract test(x: string | number): string | number; 
} 

class b extends a { 
    test(x: number): number { 
     return x; 
    } 
} 


class c extends a { 
    test(x: string): string { 
     return x; 
    } 
} 

let x: b | c; 


if (Math.random() > 0.5) { 
    x = new b() 
} else { 
    x = new c() 
}; 

x.test(1) 

はTSコンパイラからのエラーです:

おそらく、私が間違ってaproachまたはIを使用しているのであれば、TSのマニュアルを誤解 - あなたが私の目標のより良い方法を私に指摘してください可能性。
貧しいクラス名と任意の「いじくる」の不在のため 申し訳ありません - 私はTSのコンパイラエラーを強調任意のJSの遊び場を探すWebサイトcoudn'tので、私はあなたがその後、B、Cのいずれかとのxを宣言している公式のTS Playground

答えて

2

あなたがのインスタンスを作成するときifブロックのクラスでは、typescriptコンパイラはどのタイプxがあるかを知ることができません。それは問題ありませんが、問題は、数値を使ってテスト関数を呼び出そうとしており、型がbの場合にのみ可能です。コンパイラは、xがc型である可能性があると考えるので、エラーが発生します。

テストを呼び出すときに、呼び出される関数は常に提供されるパラメータと一致することをコンパイラに保証する必要があります。

次のいずれかが可能です。

  1. 変更コール署名のように両方のいずれかのタイプを受け入れる、と呼ばれている方法のそれはコンパイラに関係ありません。このよう:

    class b extends a { 
        test(x: any) { 
         return x; 
        } 
    } 
    
    class c extends a { 
        test(x : any) { 
         return x; 
        } 
    } 
    
  2. ifブロック内のメソッドを呼び出します。

    if (Math.random() > 0.5) { 
        x = new b(); 
        x.test(1); 
    } else { 
        x = new c(); 
        x.test('1'); 
    } 
    
  3. Typegu https://www.typescriptlang.org/docs/handbook/advanced-types.html#union-types:連合の種類とtypeguardsのハンドブックをチェック

    if (x instanceof b) 
        x.test(1); 
    else if(x instanceof c) 
        x.test('1'); 
    

:あなたのメソッド呼び出しをARD。

EDIT: すべての呼び出しでタイプガードする必要はありませんので、メソッド自体で型​​チェックを行うことをお勧めします。これの欠点は、コンパイラから警告を受け取らずに、誤ったパラメータでメソッドを呼び出せることです。ここではそれがどのように見えるかの例です:

abstract class a { 
    protected abstract internal(x: any): any; 

    public test(x: string | number): string | number { 
     return this.internal(x); 
    } 
} 

class b extends a { 
    protected internal(x) { 
     if (typeof x === "number") 
      return x; 
     else 
      throw new Error("Invalid argument"); 
    } 
} 


class c extends a { 
    protected internal(x) { 
     if (typeof x === "string") 
      return x; 
     else 
      throw new Error("Invalid argument"); 
    } 
} 

let x: b | c; 


if (Math.random() > 0.5) { 
    x = new b(); 
} else { 
    x = new c(); 
} 

x.test(1); 
+0

ありがとうございます。 毎回メソッドコールをタイプガードする必要があるか、または「一回限りの使用」ソリューションがあるかどうかを教えてください。 – eko24ive

+0

あなたが達成しようとしていることについてもっと知ることなく、正確に答えるのは少し難しいですが、試してみることができる例で私の答えを編集しました。 – hagner

1

をお勧めしますあなたは以下のコードは、しかし働く提供エディタによると (私はそれを理解するが、私の理解が限られているとして)のみ、BまたはCのみ、それをすることによって、それを再定義しよう:

abstract class a { 
abstract test(input: number | string) 
} 

class b extends a { 
    test(x: string) { 
     return x; 
    } 
} 

class c extends a { 
    test(x : number) { 
     return x; 
    } 
} 

let x//: b | c; 

if (Math.random() > 0.5) { 
    x = new b() 
} else { 
    x = new c() 
} 

x.test(1) 
+0

はい、それは助けるが、私はimplictに関するエラーが出る ''なぜなら「noImplicitAny」のany'タイプ:私のTSconfigでtrue'を文字列。私はそれを取り除くことができるか、または 'any'型で妥当な' x'を宣​​言します。私は明示的な変数宣言をしたいと思います - これは可能ですか? – eko24ive

関連する問題