UMA9626
@UMA9626 (UMA)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

TypeScriptにて、引数の値によって返り値の型が決まるような型の書き方ができるか

Q&A

Closed

解決したいこと

TypeScriptの型パズル初心者です。
以下のような関数の型は書けるのでしょうか?

  • 引数にnumber0が渡された場合、number型を返す
  • 引数にnumber0以外が渡された場合、number[]型を返す
  • number | number[]型は返さない

書けないようでしたらご指摘頂ければと思います。

該当するソースコード

type Func = (T: number) => number | number[] // 返り値の型をnumber | number[]にしたくない

const func: Func = (inputNum) => {
  if (inputNum === 0) return 1;
  return [...Array(Math.abs(inputNum))].map((_, i) => i); // [0, 1, 2, ...]
}

const res1: number = func(0)
// ↑以下エラーが出る
// 型 'number | number[]' を型 'number' に割り当てることはできません。
// 型 'number[]' を型 'number' に割り当てることはできません。
const res2: number[] = func(1)
// ↑以下エラーが出る
// 型 'number | number[]' を型 'number[]' に割り当てることはできません。
// 型 'number' を型 'number[]' に割り当てることはできません。

上記のように、返り値をnumber | number[]とすると、型を宣言した変数に結果を格納しようとすると型エラーとなります。
そうではなく、引数が決まれば型も決まってほしいなという思いです。

また、おそらく現実的な解決策としては「関数を分ける」かなと思っていますが、一旦分けない方向でお願いします :bow:

0

2Answer

型推論する時点で型が0であることが分かってないと(引数が定数であることが保証できない状態だと)おそらく不可能です.numberが引数のシグネチャが参照されることになります.

定数(というか0の型)が渡ってくることが保証できるならオーバーロードでできます.

3Like

Comments

  1. @UMA9626

    Questioner

    ありがとうございます!
    調べてみたところオーバーロードでやりたいことは実現できそうです :bow:

既に回答がついているようにオーバーロードを使うか、conditional typeを使って出来そうな気がします

T[] extends 0[] ? number : number[] みたいな

1Like

Your answer might help someone💌