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

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

ただいまの
回答率

90.84%

  • TypeScript

    269questions

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

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 133

s025236

score 17

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

type TestValue = string|true;
interface Test {
    [key:string] : TestValue|TestValue[];
}
function isArray($_:any):$_ is TestValue[]{return true;}
// なんかかんや処理
if( isArray($Test[$k]) ){
    const $t = $Test[$k];
} 


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

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

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


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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

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

let s: string = '';
let a: any = 'a';
let b = ['a', 0];

function foo(): string|number {
  return "foo";
}

if (typeof a === 'string') {
  s = a;
}

if (typeof foo() === 'string') {
  s = foo();                     // line 14
}

if (typeof b[0] === 'string') {
  s = b[0];                      // line 18
}

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

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


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

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

class Foo {
  constructor() {
    this.paranoia = false;
  }

  get [0]() {
    const r = this.paranoia ? 'Yes' : 'No';
    this.paranoia = !this.paranoia;
    return r;
  }
}

let a = new Foo();
console.log(a[0]); // Yes
console.log(a[0]); // No

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • TypeScript

    269questions

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