開発中にexpress-sessionでセッション認証を作っているがエラーが出たので、備忘録として記載します。
import { Request, Response } from 'express';
import { AuthService } from '../../application/services/AuthService';
type Test = import("express-session").SessionData;
const test: Test = {
cookie: {} as any,
userId: 1
};
export class AuthController {
constructor(
private AuthService:AuthService
){}
register = async (
req: Request,
res: Response
)=>{
const {email,password} = req.body;
const user = await this.AuthService.register(
email,password
);
res.json(user);
}
login = async (
req: Request,
res: Response
) =>{
const {email,password}=req.body;
const user = await this.AuthService.login(email,password);
if(!user){
return res.status(401).json({
message: "login failed"
});
}
req.session.userId = user.id;// req.session.userId = user.id;
res.json({
message: "login success"
});
}
logout = (
req: Request,
res: Response
) =>{
req.session.destroy(()=>{
res.json({message:"logout"})
});
}
}
エラー↓
The left-hand side of an assignment expression must be a variable or a property access.ts(2364) (property) Express.Request.session: session.Session & Partial<session.SessionData>
エラーの原因はこの行でした。
Number(req.session.userId) = user.id;
Number(req.session.userId) は「値を数値に変換した結果」であって、変数やプロパティではありません。そのため代入先にできず、
The left-hand side of an assignment expression must be a variable or a property access
というエラーになります。
修正
セッションに値を保存したいなら、そのまま代入します。
req.session.userId = user.id;
ただし、今度は別のTypeScriptエラーが出る可能性があります。
Property 'userId' does not exist on type 'Session & Partial<SessionData>'
その場合はexpress-sessionの型定義を拡張する必要があります。
型拡張
例えばsrc/types/session.d.tsを作成します。
import 'express-session';
declare module 'express-session' {
interface SessionData {
userId: number;//userId?: number;
}
}
export {};
tsconfig.json でこのファイルが読み込まれる場所にあることも確認してください。
tsconfig.jsonを新規作成
TypeScriptプロジェクトなのにtsconfig.jsonがない場合、TypeScriptはデフォルト設定で動作するため、型拡張ファイル(express-session.d.ts など)が認識されないことがあります。
まずプロジェクトルートで実行します。
npx tsc --init
するとtsconfig.jsonが生成されます。
Express + Node.js なら最低限こんな感じがおすすめです。
{
// Visit https://aka.ms/tsconfig to read more about this file
"compilerOptions": {
// File Layout
"rootDir": "./src",// コメントアウト解除
"outDir": "./dist",// コメントアウト解除
// Environment Settings
// See also https://aka.ms/tsconfig/module
"module": "CommonJS",//nodenext
"target": "ES2022",//esnext ES2022
"esModuleInterop": true,
"types": [],
// For nodejs:
// "lib": ["esnext"],
// "types": ["node"],
// and npm install -D @types/node
// Other Outputs
"sourceMap": true,
"declaration": true,
"declarationMap": true,
// Stricter Typechecking Options
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
// Style Options
// "noImplicitReturns": true,
// "noImplicitOverride": true,
// "noUnusedLocals": true,
// "noUnusedParameters": true,
// "noFallthroughCasesInSwitch": true,
// "noPropertyAccessFromIndexSignature": true,
// Recommended Options
"strict": true,
"jsx": "react-jsx",
"verbatimModuleSyntax": false,// true
"isolatedModules": true,
"noUncheckedSideEffectImports": true,
"moduleDetection": "force",
"skipLibCheck": true,
},
"include": ["src/**/*"]
}
package.jsonの修正
全体のpackage.jsonは下記のとおりです。
{
"dependencies": {
"@types/pg": "^8.20.0",
"bcrypt": "^6.0.0",
"cors": "^2.8.6",
"dotenv": "^17.4.2",
"express": "^5.2.1",
"express-session": "^1.19.0",
"pg": "^8.22.0"
},
"devDependencies": {
"@types/bcrypt": "^6.0.0",
"@types/cors": "^2.8.19",
"@types/express": "^5.0.6",
"@types/express-session": "^1.19.0",
"@types/node": "^26.0.0",
"ts-node-dev": "^2.0.0",
"typescript": "^6.0.3"
},
"scripts": {
"dev": "ts-node-dev --respawn --files src/app.ts",
"build": "tsc",
"start": "node dist/app.js"
}
}
