【TypeScript】型定義しない時あるのなんでなん?(初心者向け)
投稿日: 2024年11月26日
TypeScriptの章に入りたての頃、型を書いてる時と書いてない時があるけど、何が違ってそうなっているのかわからないと思いました。
私と同じ状況の方に向けて書いてみます。
any型の値となるのを避ける
この方針で型付けしていますし、これでいいのではないかと思います。
ただ一部(思いつくのはobject型) anyにはならないけど避けた方がいい型はあります。
なぜanyがダメかというと、anyにはどんな型の値でも入ってしまうので、TypeScriptの型安全であるというメリットがその値に関しては失われてしまうためです。
危険な例を見てみます。
const printLength = (array: any) => {
console.log(array.length);
};
printLength(10)
これ実行した時にエラー吐きますよね。
「lengthはありません~」みたいなエラーがコンソールに出力されるはずです。(試さなくてすみませんw)
printLengthの引数は配列であることを前提に処理しています。
でも関数に渡しているのは数値です。
any型にしているので型チェックされずエディターでエラーでません・・(怖い)
型定義しっかりすると、
const printLength = (array: number[]) => {
console.log(array.length);
};
printLength(10)
エラー吐いてくれるのでオッと配列渡すんだった・・となるわけです。(心強い)
const processInput = (input: object) => {
//inputがどんなプロパティを持ってるかわからない
console.log(input);
};
processInput({});
オブジェクト型であれば中身が空でもエラーなく受け入れてしまいます。。(コワイ)
type User = {
id: number;
name: string;
};
const processInput = (input: User) => {
console.log(input);
};
processInput({});
こうするとprocessInputはUser型のオブジェクトしか受け付けないのでエラー吐いてくれて型安全が確保されます!
TypeScriptでは型を自動的に推論してくれるありがたい機能があります。
例えば、
let mystring = "文字列";
このmyStringという変数はstringと推論されます。
constで宣言すると再代入不可能な時点で"文字列“以外入りえない定数となるので文字列リテラル型と推論されます。
こういったときはわざわざ
let mystring:string = "文字列";
としなくてOKです。
言わなくても"文字列“入れてる時点でわかるからです。
const items = [];
items.push("文字列");
items.push(42);
この場合、itemsはany[]
と推論されるので文字列でも数値でも受け入れます。
危険。。
const items: string[] = [];
items.push("文字列");
items.push(42);
この場合、
エラーになるので間違えて数値入れなくてよかった・・となりますね。
APIで受け取ったレスポンスに関してはどうでしょう。
const resp = await fetch("/api/posts/", { method: "GET" });
const data = await resp.json();
respの型はResponse型と推論されています。
その下のdataは・・?
anyです。
これはレスポンスがどんな型なのか確認して定義した方がいいです。
存在しないプロパティ(タイポ含む)にアクセスしようとしてundefindeになってたみたいなことも起きます。
レスポンスにhogeというプロパティが存在しない場合もエラーにはならないのです。
コンソールに出力されるのはundefindeになると思います。
存在する前提でコード書き進めるとその先でエラー発生するというのがよくありそうです。
上手くいかない~と相談いただいて見ているとレスポンスの型定義していなくて、プロパティ名のタイポでというケース少なからずあります!
なんでもいけるんですよね・・(コワイ)
dataを使ったその後の処理の際にも型を定義しておくと全部定義した通りに補完機能が働くので絶対定義した方が便利です。
補完機能については「え~っと、、このオブジェクトってどんなプロパティ持ってたっけ~」と見に行かなくても、data.
で型情報をもとに存在するプロパティ候補を挙げてくれます。
これに慣れると絶対全部型定義した方が自分が楽になるしエラー減らせるから結果早いと実感して、TypeScriptなくてはならない存在になります。
型定義しない時あるのなんでなん→型推論があるから!!です。
なにに定義したらいい? ?ってなったらanyがないように!と思って型つけてみてください!!!!!
定義してなくても推論されてたら明示的に定義しなくてOKです!!
ステートも無駄に型引数渡すことある気がします(ダメではないけど絶対必要ではない)
const [data, setData] = useState("");
初期値が空の文字列なのでdataはstringと推論されます。
const [data, setData] = useState<string>("");
こうしてもいいけどしなくてもいいって感じです。
初期値をnullにするときは型引数で<string|null>
としましょう!!
const [data, setData] = useState<string|null>(null);
TypeScriptって最初はわけわかんないのですが、身についてくるとないと不安な存在になります!!
そんな日が早く来る助けになればいいなと思います!!