0
0

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 1 year has passed since last update.

Typescriptでメソッドの戻り値によって型付けを保証したい(Argument of type xxxx is not assignable to parameter of type xxxxの対処)

Posted at

Typescriptを使っている際、よく下記のようなシチュエーション、書き方をしたくなりますよね。
①ある変数がnull、undefinedの可能性がある
②ある変数をisNotNullメソッドにてnull, undefinedでないことをチェックする
③nullでないことが保証されたある変数を別のメソッドに渡す
④Argument of type undefined is not assignable to parameter of type xxxxのエラー
いやいや、isNotNullメソッドでundefinedでないことチェック済やんけ。。。という感じなのですがtsc的にはエラーを出してきます。

type Status = 'success' | 'failuer';
const messages: { [key in Status]: string } = {
  success: '成功',
  failuer: '失敗',
};

const isNotNull = (status: Status | undefined) => {
  if (status == null) {
    return false;
  }

  return true;
}

const getMessage = (status: Status) => {
  return messages[status];
}


let st;

if (isNotNull(st)) {
  console.log(getMessage(st));
  // undefinedではないことをisNotNull関数でチェックしているのに、エラーとなってしまう
  // Argument of type 'undefined' is not assignable to parameter of type 'Status'.
}

対処法①(Bad)

型アサーションや!を使って無理やり解決できますが、Typescriptの型システムを
台無しにしてしまうので避けたほうが良いです

type Status = 'success' | 'failuer';
const messages: { [key in Status]: string } = {
  success: '成功',
  failuer: '失敗',
};

const isNotNull = (status: Status | undefined) => {
  if (status == null) {
    return false;
  }

  return true;
}

const getMessage = (status: Status) => {
  return messages[status];
}


let st;

if (isNotNull(st)) {
  console.log(getMessage(st as any)); // 型アサーションで無理やり解決する
}

対処法②(Good)

メソッドの戻り値に型付けを行えます。
下記で、isNotNullメソッドの戻りがtrueであればundefinedでないことを明示してみます。
ただし、isNotNull自体がバグっている場合でもtrueが返却されるとその型で認識されてしまうので注意が必要です。
(ここはなんだかなーというところ)

type Status = 'success' | 'failuer';
const messages: { [key in Status]: string } = {
  success: '成功',
  failuer: '失敗',
};

// メソッドの戻り値で型付けを行う(status is Statusの部分)
// trueが返った場合、statusはStatus型であるという表現になる
const isNotNull = (status: Status | undefined): status is Status => {
  if (status == null) {
    return false;
  }

  return true;
}

const getMessage = (status: Status) => {
  return messages[status];
}

let st;

// isNotNullがtrueの場合、statusはStatus型であるとtscが認識するため、
// コンパイルエラーは出ない
if (isNotNull(st)) {
  console.log(getMessage(st));
}

// falseの場合はもちろんエラー出る
if (!isNotNull) {
  console.log(getMessage(st));
  // Argument of type 'undefined' is not assignable to parameter of type 'Status'.
}

私のレベルの問題かもしれませんが初めて知った時感動しました。
この手のエラーは困ることあるけど、ググり方もわからないし調べづらいので
お役に立てば幸いです。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?