質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

2回答

381閲覧

TypeGuardを使ってるのに型推論が思った様に効かず困っています

s025236

総合スコア27

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

2クリップ

投稿2018/05/18 08:22

編集2018/05/18 10:38

TypeScript 2.8.3を利用しています。
tscが以下のコードで$tstring | true | TestValue[]だと言い張ります。

TypeScript

1type TestValue = string|true; 2interface Test { 3 [key:string] : TestValue|TestValue[]; 4} 5function isArray($_:any):$_ is TestValue[]{return true;} 6// なんかかんや処理 7if( isArray($Test[$k]) ){ 8 const $t = $Test[$k]; 9}

当然const $t:TestValue[] = $Test[$k];でも型が合わないのでエラーになります。

以下の様に一旦変数に入れてからTypeGuardを通すと正しく推論されます。

TypeScript

1const $t = $R[$k]; 2if(isArray($t)){ 3 $t;//これだとTestValue[]と認識される 4}

またasで型を強制する事でエラーが出ない様に出来る事も解っています。

TestValue[]なのは自明に見えるのに何故このような挙動になるのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

詳しい説明ありがとうございました。

getter/setterやIteratorがある(それをすっかり忘れてた)ので
間にまったく処理が入っていなくても配列やオブジェクトの要素は寸前の評価と違う値になる可能性がある為
「自明に見える」と思い込んでるのがそもそも間違っていました。

理由がわかったのでArrayか評価後asで強制的に型変換すると言う対応に自信が持てました。

投稿2018/05/21 04:49

s025236

総合スコア27

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

TypeScript/JavaScriptに暗く、あてずっぽうに近いコメントです・・・

typescript

1let s: string = ''; 2let a: any = 'a'; 3let b = ['a', 0]; 4 5function foo(): string|number { 6 return "foo"; 7} 8 9if (typeof a === 'string') { 10 s = a; 11} 12 13if (typeof foo() === 'string') { 14 s = foo(); // line 14 15} 16 17if (typeof b[0] === 'string') { 18 s = b[0]; // line 18 19}

hello.ts(14,2): error TS2322: Type 'string | number' is not assignable to type 'string'.

Type 'number' is not assignable to type 'string'.

line 18でも同じエラー

tscのこの振る舞いを見るとプロパティーの参照は関数呼び出しなどと同様、「冪等でない」という前提があるように思えました。質問者さんがやっておられるように

typescript

1const tmp = b[0]; 2if (typeof tmp === 'string') { 3 s = tmp; 4}

ならコンパイルエラーになりませんね・・・

JavaScriptの言語仕様でプロパティーの参照が冪等である(べき)かどうかは自分には分かりません。ただ、以下のように書けてしまうということを考えると「TypeScriptはそれを冪等でないと見做します」と言われれば納得できる気がしました。

js

1class Foo { 2 constructor() { 3 this.paranoia = false; 4 } 5 6 get [0]() { 7 const r = this.paranoia ? 'Yes' : 'No'; 8 this.paranoia = !this.paranoia; 9 return r; 10 } 11} 12 13let a = new Foo(); 14console.log(a[0]); // Yes 15console.log(a[0]); // No

投稿2018/05/19 03:12

編集2018/05/19 10:19
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問