frontendmemo

このサイトは、「html、css、js、ruby,ツールなどについて、自分が覚えたこと、またはいつも忘れて調べることを書き溜め、それが結果といて勉強したての初心者の方や自分と同じような技術レベルの人の助けになることを目的とするWebログ」、略してブログです。挨拶→http://frontendmemo.hatenablog.com/entry/2016/06/25/115845

typescriptの型エラーをなんとかしたい!anyよ、さよなら。エラーの解決法

スポンサードリンク


スポンサードリンク


TypeScriptは型付けできるJSですが、そのエラーの多さに嫌気が指してしまうのは自分だけではないはずです。

この記事ではTypeScriptの何が難しいのか、実際自分がエラーにあたって解決した事例を書いていきます。
尚、勉強中故、正しい情報とは限りませんので他の記事も参考にしつつ最適解を探してみてください。

TypeScript案件の進め方

はじめに1か月TypeScript案件をやってみての感想を進め方をもとに書きます。


型付けしながら実装するわけですが、「どうしても何の型かわからん!」という時は一旦anyにしておくのも手です。

なぜなら、そこに膨大な時間を使うよりまず動くように作れというのがプログラミングにおいては一般的な進め方だと思うからです。
その後、余った時間でじっくり型定義してからでもおそくはありません。


また一箇所で何個もエラーが出るので一つずつanyから変えていくというのも手かと思います。

がんばらないTypeScriptというありがたいお言葉の記事があります。
そこにはanyを使っても問題ないという記述があります。

しかし、型システムをマスターしなければTypeScriptで開発できないわけではありません。複雑な型演算*2は、アプリケーションを書くときに必要になることはほとんどありません。またほかの多くの静的型付き言語と異なり、型エラーで困ったときはいつでもanyで握りつぶせます。動くことが分かっているコードで遭遇する型エラーを握りつぶすのは、特にJavaScriptをTypeScriptに置き換えるフェーズでは、ためらわずにやる方がよいと思っています。

TypeScript再入門「がんばらないTypeScript」で、JavaScriptを“柔らかい”静的型付き言語に(gfx執筆) - エンジニアHub|若手Webエンジニアのキャリアを考える!

しかし、実際それではTypeScriptの意味がなく、最適解がある以上anyを使うことは現場でも容認されないというのが実態かと思いますし自分もそれに賛同しています。

TypeScript型の一覧

TypeScript型の一覧は以下です。

  • number
  • boolean
  • string
  • void(変数としては定義不可)
  • null(同上)
  • undefined(同上)

型定義の何が難しいのか


実践TypeScriptの著者吉井健文さんも本の冒頭で下記のようにおっしゃってます。

「TypeScriptを導入したものの、手間ばかりかかってしまい、結局JavaScriptに戻してしまったという話も少なくありません」


制作現場ではTypeScriptの扱いづらさに混乱をきたしている状態なわけです。


では型定義の何が難しいのでしょう。


自分も実案件に入る前は、const val: number = 1000くらいにしか考えてませんでした。

オブジェクトの型定義の難しさ


objectを型定義しようとしたときobjectにするとエラーになることがあります。


下記はエラーにならない。

const user = {
    val: true,
    key: 1,
    state: {
        login: 'active'
    }
}
function greeter(person: object) {
    return "Hello, " + person;
}
document.body.innerHTML = greeter(user);


しかしAPI呼び出して使用する場合、型定義ファイルをimportで読み込んだ場合エラーになります。


もしかしたらこんなエラーが出るかもしれません。

Element implicitly has an 'any' type because type '{}' has no index signature.

api.ts
export type ApiType = {
  key1: number
   key2: string
  key3: string
}

index.vue
public api: Array<ApiType> = []

上記のようにオブジェクトを配列にする必要があります。

また型をobjectにした場合その中のkeyでエラーが出ることもあるようです。

Property 'name' does not exist on type 'object'
api.key.name

エラーObject is possibly 'undefined'.

上記エラーの場合 undefinedの可能性もあるのにobjectで型定義してしまってるとなります。

Non-null assertion operatorという(!)を末尾に付けることでこのエラーを回避することができます。
意味としては「この変数はundefinedやnullにならない」ことを意味します。

後々型が変更している

後々型が変更した場合ももちろんエラーになります。(そのための型定義)
なので変数定義から道筋をたどって実装するとよさそうです。


以上、TypeScriptで躓いた一部ですが今後も追記していこうと思います。