16
5

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 3 years have passed since last update.

TypeScriptのnever型について

Posted at

never型って?

typeScriptにおけるbottom型です。

bottom型って何よ

型理論、数理論理学において値を持たない型のことである

↑wikiからの抜粋です。
値を持たない型, これだけだと???となりそうですが、

戻り値の型がボトム型である関数は、いかなる値も返さない。

こちらの説明だと少しわかりやすいかと思います。

つまり、

const foo = () => {
 while(true){}
}

上記のようにwhile(true)で戻り値がない場合(= returnが絶対に走らない場合)などは、関数fooの戻り値の型はneverと言えます。

スクリーンショット 2020-08-02 11.27.54.png

特徴

neverは値のない型なので、値を入れるとエラーになります。

let foo:never

foo = 'test' // コンパイルerror

実際に戻り値がneverとなる例

上記でwhileの例を上げましたが、他の例とも合わせて再掲します。

// 無限ループする場合
const foo = () => {
 while(true){}
}

// errorをthrowする場合
const bar = () => {
    throw new Error("これはエラーです")
}

voidneverの違いは?

これは実際にコードを見てもらった方がわかりやすいです。

const foo = () => {
}

const bar = () => {
    return 
}

const baz = () => {
    while(true){}
}


let fooVar:never = foo() // error
let barVar:never = bar() // error
let bazVar:never = baz() //ok!

上記では bazのみ戻り値がnever型で、 foobarの戻り値はvoid型です。

JSに置いてreturn文を省略された場合はundefinedが返る仕様なので、
foobarは実質的に同じです。

voidはreturnでの戻り値なし!の型なのに対して
neverはそもそもreturnしない。 
似ているようで全然違っています。

実際での使用例

値を入れることができない という部分が生きてきます。

下記のような型がそれぞれあったとします。

interface Neko {
    type: "neko"
}

interface Inu {
    type: "inu"
    name: number
}
interface Other {
    type: "other"
}

type Animal = Neko | Inu | Other

上記Animal型を使う上で、typeによってそれぞれ別の処理をさせたい場合、
下記のようなコードになるかと思います。

function intro(s: Animal) {
    if (s.type === "neko") {
        return `吾輩は猫である。名前はまだない`
    }
    else if (s.type === "inu") {
        return `${name}は犬のお廻りです。`
    }
}

上記ではNeko Inu の型しか想定されていません。
Other型, またそれ以外でも想定しない型が渡ってきた場合にerrorを返す仕組みがあれば便利です。
そこで、予期しない型が渡ってきた場合はneverに代入することでコンパイルエラーを出し、
網羅漏れに気づくことができます。
(全て網羅できていれば、 _exhaustiveCheckはnever型となります。)


function intro(s: Animal) {
    if (s.type === "neko") {
        return `吾輩は猫である。名前はまだない`
    }
    else if (s.type === "inu") {
        return `${name}は犬のお廻りです。`
    }
    else {
        // Otherが渡ってきた場合、neverの特徴によってerrorが出て気づくことができる。
        const _exhaustiveCheck: never = s;
    }
}

上記の手法はswitchのdefault文に置いても有効ですね。

参考文献

TypeScript Deep Dive 日本語版
Use the never type to avoid code with dead ends using TypeScript
TypeScriptの型入門

wiki ボトム型

16
5
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
16
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?