TypeScript

Lesson 03

Avoiding unsafe assertions

Prefer checks that prove a value's shape over assertions that silence the compiler.

Good Code

session.ts
type Session = {
  userId: string;
  expiresAt: string;
};

function isSession(value: unknown): value is Session {
  return (
    typeof value === "object" &&
    value !== null &&
    "userId" in value &&
    typeof value.userId === "string" &&
    "expiresAt" in value &&
    typeof value.expiresAt === "string"
  );
}

export function readSession(value: unknown): Session | undefined {
  // Runtime checks prove the value before exposing Session.
  if (!isSession(value)) {
    return undefined;
  }

  return value;
}

Bad Code

session.ts
type Session = {
  userId: string;
  expiresAt: string;
};

export function readSession(value: unknown): Session {
  // Assertion turns unknown data into Session without evidence.
  return value as Session;
}

Review Notes

What to review

Good Code

The good version earns trust by checking the runtime shape before returning typed application data.

Bad Code

The bad version tells TypeScript to accept the value as a Session without proving anything, so invalid data can move through the app as if it were safe.

Takeaways

  • Treat `as` as a last resort at trusted boundaries, not a way to skip validation.