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?

【TypeScript】any型について

Posted at

はじめに

本記事を書くきっかけですが、
現在、G's EXPANSION PROGRAMというG'sのアドオンプログラムで、
TypeScriptを学ぶことにあり、
その課題でany型について調べることになりました。

TypeScriptで実装した際に、下記のような経験がありました。

  • 型エラーが出たからとりあえず any をつけた
  • any を使ったら動いたけど、なんかモヤモヤする
  • レビューで「any使わないで」と言われたけど、代わりに何を使えばいいかわからない

この記事では、any型のついてと、より安全な代替手段を具体例つきで解説します。

any型とは?

一言でいうと、TypeScriptの型チェックを完全にオフにする型です。

let value: any = 42;
value = "hello";        // ✅ OK
value = { x: 1 };       // ✅ OK
value = null;           // ✅ OK

// 何でも設定できてしまう(危険)
value.foo();            // ✅ コンパイル通る → 💥 実行時エラー
value.bar.baz.qux;      // ✅ コンパイル通る → 💥 実行時エラー

つまりany型は、TypeScriptの型システムを無視し、
JavaScriptを書いているのと同じ状態になります。

なぜanyは問題なのか?

1. タイポを見逃す

interface User {
  id: number;
  name: string;
}

function greet(user: any) {
  // 😱 nameをnmaeとタイポしてもエラーにならない
  console.log(`Hello, ${user.nmae}!`);
}

greet({ id: 1, name: "田中" });
// 出力: Hello, undefined!

2. 存在しないメソッド呼び出し

function processData(data: any) {
  // 😱 配列じゃなくてもmapが呼べてしまう
  return data.map((item: any) => item.value);
}

processData("これは文字列");  // 💥 実行時エラー

3. anyは「感染」する

function getUserData(): any {
  return { id: 1, name: "田中" };
}

// 戻り値を受け取った変数も any になる
const user = getUserData();
const userName = user.name;  // userName も any 😱

// どんどん型安全性が失われていく...

anyの代替手段

🥇 最も推奨:具体的な型を定義する

最も安全で、TypeScriptを使う意味がある方法です。

// ❌ Before
function processUser(user: any) {
  return user.name.toUpperCase();
}

// ✅ After
interface User {
  id: number;
  name: string;
  email?: string;
}

function processUser(user: User) {
  return user.name.toUpperCase();
}

🥈 柔軟性が必要な場合:ジェネリクスを使う

「いろんな型を受け取りたいけど、型安全も保ちたい」場合に最適です。

// ❌ anyで何でも受け取る
function getFirst(arr: any[]): any {
  return arr[0];
}
const item = getFirst([1, 2, 3]);  // item は any 😱

// ✅ ジェネリクスで型を保持
function getFirst<T>(arr: T[]): T {
  return arr[0];
}
const item = getFirst([1, 2, 3]);  // item は number ✨
const name = getFirst(["a", "b"]);  // name は string ✨

制約をつけてさらに安全に:

// T は最低限 id を持つ型に限定
function findById<T extends { id: number }>(items: T[], id: number): T | undefined {
  return items.find(item => item.id === id);
}

// ✅ User型の配列を渡せば、戻り値もUser型
const users: User[] = [{ id: 1, name: "田中" }];
const found = findById(users, 1);  // found は User | undefined

🥉 外部データには:Zodでランタイム検証

APIレスポンスやフォーム入力など、実行時まで中身がわからないデータには、コンパイル時の型チェックだけでは不十分です。

import { z } from "zod";

// スキーマ定義
const UserSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
});

// スキーマから型を自動生成
type User = z.infer<typeof UserSchema>;

// APIレスポンスを安全にパース
async function fetchUser(id: number): Promise<User> {
  const response = await fetch(`/api/users/${id}`);
  const json = await response.json();

  // ✅ 実行時に検証 + 型がつく
  // 不正なデータならここでエラーになる
  return UserSchema.parse(json);
}

代替手段の選び方まとめ

シチュエーション 推奨する方法
型がわかっている 具体的な型・interfaceを定義
複数の型を柔軟に扱いたい ジェネリクス
外部からのデータ(API等) Zod等でランタイム検証

tsconfig.jsonでanyを制限する

チームでの開発では、設定で any を制限しましょう。

{
  "compilerOptions": {
    // 暗黙的なanyを禁止(型推論できない場合にエラー)
    "noImplicitAny": true,

    // 上記を含む厳格モード(推奨)
    "strict": true
  }
}

noImplicitAnyの効果

// noImplicitAny: false の場合
function add(a, b) {  // a, b は暗黙的に any
  return a + b;
}

// noImplicitAny: true の場合
function add(a, b) {  // ❌ エラー: Parameter 'a' implicitly has an 'any' type.
  return a + b;
}

// ✅ 型を明示する必要がある
function add(a: number, b: number) {
  return a + b;
}

まとめ

覚えておきたいポイント

  1. any は「TypeScriptをやめる」のとほぼ同じ
  2. まず具体的な型定義を検討する
  3. 柔軟性が必要ならジェネリクス
  4. 外部データにはZod等でランタイム検証
  5. strict: true で暗黙の any を防ぐ

anyを使いたくなったら、まず「本当に型がわからないのか?」を自問してみてください。 多くの場合、型を定義できるはずです。


参考リンク


最後まで読んでいただきありがとうございました!

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?