Here’s what the auth fixes were doing, concept by concept.
any vs explicit typesWith strict on, untyped parameters become errors (implicitly has an 'any' type).
header, callback, req, res, next needed real types so TypeScript could check how you use them.
@types/...)jsonwebtoken is JS; types come from @types/jsonwebtoken. That gives you:
JwtHeader — token header shape (kid, alg, …)SigningKeyCallback — (err, key) => void for jwt.verifyJwtPayload — decoded claims (sub, aud, …)Same idea as @types/express for Request / Response / NextFunction.
import typeimport type { NextFunction, Request, Response } from "express";
Imports types only — erased at runtime. Safer with verbatimModuleSyntax because it can’t accidentally pull in a runtime value.
TypeScript won’t trust optional/union values until you check them:
if (!header.kid) → after that, header.kid is stringif (!key) → after that, key is definedif (!decodedClaims || typeof decodedClaims === "string") → remaining branch is JwtPayloadThat’s control-flow narrowing: the type gets smaller after each check.