TypeScriptバージョン: 2.3.2
コード
// example.js
var Person = function (firstNameOrPojo, lastName) {
if (typeof firstNameOrPojo === "string") {
this.firstName = firstNameOrPojo;
this.lastName = lastName;
} else {
return new Person(firstNameOrPojo.firstName, firstNameOrPojo.lastName);
}
};
Person.prototype.greet = function greet() {
return `Hello, I am ${this.firstName} ${this.lastName}.`;
};
var fred = new Person({firstName: "Fred", lastName: "Flintstone"});
console.log(fred.greet());
予想される行動:
特に返される型が常に期待される型と一致することを考えると、 tsc
がエラーや警告なしにこのコードをコンパイルすることを期待します。
JavaScriptでは、コンストラクター関数がオブジェクトを返すことが可能です。 これが行われると、返されるオブジェクトはnew
式全体の結果になります(新しい演算子については、この
型に関心があると、TypeScriptコンパイラがJavaScript言語のこの癖をサポートすることを躊躇する理由がわかります。 結局のところ、コンパイラは、明示的に返される値が、 undefined
返した場合にコンストラクタから返される値と同じであることを確認する必要があります(通常の場合)。 これはサポートされるべきだと思います。理由は次のとおりです。
これは便利で人気のあるJavaScriptテクニックです
上記のコードは、Node.jsとブラウザーで問題なく実行されます。
$ node example.js
Hello, I am Fred Flintstone.
実際の動作:
tsc
は、このコードをチェックするときにエラーを発行します。
$ tsc --allowJs --checkJs --outDir ./dist example.js
example.js(8,16): error TS2350: Only a void function can be called with the 'new' keyword.
何を返すかに関係なく、タイプは実際には正しく理解されます。 コンパイラーは、関数として呼び出されたときに戻り値の型を使用し、コンストラクターとして使用されたときにインスタンス型を使用することを認識しています。 エラーは、.jsファイルで対処する必要があるものです。 パターンはまだ.tsファイルには許可されていません(保守的な側でエラーが発生したため)。
+1
特にProxy
ができたので、クラスインスタンスの代わりにプロキシを直接返すことで実装できる優れた動作があります。 しかし、コンストラクターの戻り値の型を推測または指定できない限り、それは不可能です。
あなたが置くことができればget(target, name) {}
そしてset(target, name, value) {}
クラスコンストラクター内で、Object / Array(のすべてのプロパティ)のプロパティ代入演算子をオーバーライドします。そうすれば... javascriptが不足することはありません。
[それ以外の場合は、ハンドラー関数を使用して新しいプロキシを返すだけで十分です。]
最も参考になるコメント
+1
特に
Proxy
ができたので、クラスインスタンスの代わりにプロキシを直接返すことで実装できる優れた動作があります。 しかし、コンストラクターの戻り値の型を推測または指定できない限り、それは不可能です。