2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[TypeScript 3.5] 型が指定されていない場合の型推論の仕様変更について

Last updated at Posted at 2019-06-21

今まで空のオブジェクト{}として推論されていたのですが、TypeScript3.5から導入されたunknownが推論に使用されるようになりました。
タイプ定義が無いライブラリ等を使用している場合、今まで通ってたコンパイルが結構通らなくなる可能性が高いです。
私もかなりの数のエラーが発生しました。

unknown型について

{}unknownは似ておりますが、以下の違いがあります。

  • {}は文字列でインデックス参照ができます(例: k["foo"])が、unknownはできません
  • {}nullundefinedではないとみなされるが、unknownnullundefinedの可能性があります
  • {}はオブジェクトに代入可能ですが、unknownはできません

対策

例として、型定義がないライブラリのフック関数等を定義する場合を考えます。

// 今まで型が未定義の場合は以下のように`{}`と推論されていた
// type HookType = (args: {}) => void;
// 3.5からは`unknown`型と推論される
type HookType = (args: unknown) => void;

const hook: HookType = args => {
  // error: Object is of type 'unknown'.
  console.log(args.hoge);
};

対策としてはまず、無理やりキャストする方法があります。

const hook: HookType = args => {
  const castedArgs = args as { hoge: any };
  // ok
  console.log(typedArgs.hoge)
}

ただ、無理やりキャストするよりもUser-Defined Type Guardsを使いましょう。
https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards

返り値の型に引数名 is 型のように指定することでタイプガードを定義することができます。
これを使って条件式を書くことで、型の推論を限定する(narrow)ことができます。

const hasHogeProperty(args: any): args is { hoge: any } => {
  if (!data) return false;
  if (data.hoge) {
    return true;
  }

  return false;
}

const hook: HookType = args => {
  if (hasHogeProperty(args)) {
    // ok
    console.log(args.hoge)
  }
}
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?