「Next.jsでつくるフルスタックアプリwith TypeScript 前編」の感想・備忘録2

スポンサーリンク
「Next.jsでつくるフルスタックアプリwith TypeScript 前編」の感想・備忘録1の続き

userディレクトリのTypeScript化

pages/api/user/register.jsのtypeScript化

  • mv pages/api/user/register.js pages/api/user/register.ts
  • reqはutils/types.tsに新たな型定義ExtendedNextApiRequestUserを追加する。
  • resをNextApiResponse<ResMsgType>とする。
import type {NextApiResponse} from "next"; // 追加
import connectDB from '../../../utils/database'
import { UserModel } from "../../../utils/schemaModel";
import { ExtendedNextApiRequestUser, ResMsgType } from '../../../utils/types' // 追加

 // : ExtendedNextApiRequestUserと: NextApiResponse<ResMsgType>を追加
const registerUser = async (req: ExtendedNextApiRequestUser, res: NextApiResponse<ResMsgType>) => {
  try {
    await connectDB();
    await UserModel.create(req.body)
    return res.status(200).json({ msg: '登録しました。' })
  } catch (err) {
    return res.status(400).json({ msg: '失敗しました。' })
  }
}
export default registerUser;

utils/types.tsの修正

  • ExtendedNextApiRequestUser型を追加
  • ExtendedNextApiRequestUserのbodyはUserDataType型とする。
import type {NextApiRequest} from "next";

// schemaModel.ts
export interface ItemDataType {
  title: string,
  image: string,
  price: string,
  description: string,
  email: string
}
export interface UserDataType {
  name: string,
  email: string,
  password: string,
}

// auth.ts
export interface DecodedType  {
  email: string
}

export interface ExtendedNextApiRequestAuth extends NextApiRequest {
  headers: {
    authorization: string
  },
  body: {
    email: string
  }
}

// 追加
// register.ts, login.ts
export interface ExtendedNextApiRequestUser extends NextApiRequest {
  body: UserDataType
}

// common
export interface ResMsgType {
  msg: string
}

pages/api/user/login.jsのtypeScript化

  • mv pages/api/user/login.js pages/api/user/login.ts
  • req, resはpages/api/user/register.jsと同じ修正内容。
  • savedUserはUserDataTypeを使うことができる見えるが、_idが必要になるためtypes.tsにUserDataTypeを継承した型定義を追加する。
  • DBからはnullが返ることもあるのでユニオンを使ってSavedUserDataType | nullとする。
import type {NextApiResponse} from "next"; // 追加
import jwt from 'jsonwebtoken'
import connectDB from '../../../utils/database'
import { UserModel } from "../../../utils/schemaModel";
import { ExtendedNextApiRequestUser, SavedUserDataType, ResMsgType } from '../../../utils/types' // 追加

 // : ExtendedNextApiRequestUserと: NextApiResponse<ResMsgType>を追加
const loginUser = async (req: ExtendedNextApiRequestUser, res: NextApiResponse<ResMsgType>) => {
  try {
    await connectDB();
    // : SavedUserDataType | nullを追加
    const savedUser: SavedUserDataType | null = await UserModel.findOne({email: req.body.email});
    if (savedUser && req.body.password === savedUser.password) {
      const token = jwt.sign({email: req.body.email}, 'hogehogehoge', {expiresIn: '23h'});
      return res.status(200).json({ msg: 'ログインに成功しました。', token: token });
    } else {
      return res.status(400).json({ msg: 'ログインに失敗しました。' })
    }
  } catch (err) {
    return res.status(400).json({ msg: 'エラーが発生しました。' })
  }
}
export default loginUser;

utils/types.tsの修正

  • ResMsgTypeにtoken?: stringを追加する。
    ※ tokenはpages/api/user/login.jsのレスポンスにだけ必要なので?をつけて省略可能とする。
  • _idはmonggoseパッケージのTypes.ObjectId型となる。
import type {NextApiRequest} from "next";

// schemaModel.ts
export interface ItemDataType {
  title: string,
  image: string,
  price: string,
  description: string,
  email: string
}
export interface UserDataType {
  name: string,
  email: string,
  password: string,
}

// auth.ts
export interface DecodedType  {
  email: string
}

export interface ExtendedNextApiRequestAuth extends NextApiRequest {
  headers: {
    authorization: string
  },
  body: {
    email: string
  }
}

// register.ts, login.ts
export interface ExtendedNextApiRequestUser extends NextApiRequest {
  body: UserDataType
}

// 追加
// login.ts
export interface SavedUserDataType extends UserDataType {
  _id: Types.ObjectId
}

// common
export interface ResMsgType {
  msg: string,
  token?: string // 追加
}

コメント