Skip to content

Add author and createdAt to the Event type and drop double casts #48

Description

@ameyypawar

The Event interface declares neither author nor createdAt, but addEvent writes both to Firestore and the read paths add createdAt back on the way out. The mismatch is currently hidden by three as unknown as Event double casts, which silence the compiler without making the type correct, and it surfaces as a hard error in searchService, which builds its event objects without a cast.

Location

  • src/lib/types.ts:19-30 — the Event interface
  • src/lib/services/eventService.ts:26-32 — where author and createdAt are written
  • src/lib/services/eventService.ts:51, :70, :90 — the three double casts
  • src/lib/services/searchService.ts:163 — the resulting type error

The write stores both fields:

    const docRef = await addDoc(collection(db, 'events'), {
      ...eventData,
      author,
      dateTime: dateTime.toISOString(),
      createdAt: serverTimestamp(),
      rsvpCount: 0,
    });

The reads add createdAt and then cast the shape away, three times over:

      return {
        ...data,
        id: docSnap.id,
        createdAt: data.createdAt?.toDate ? data.createdAt.toDate().toISOString() : new Date().toISOString(),
        dateTime: typeof data.dateTime === 'string' ? data.dateTime : (...),
      } as unknown as Event;

searchService does the same mapping without a cast and fails:

src/lib/services/searchService.ts(163,9): error TS2353: Object literal may only specify known properties, and 'createdAt' does not exist in type 'Event'.

The file already acknowledges both fields — EventDataForFirestore at eventService.ts:8-12 and the addEvent parameter at :16 both Omit 'createdAt' and 'author' from Event. Omit does not require the keys to exist, so those lines compile while documenting fields the type never declared.

Why this matters

as unknown as Event turns off checking for the whole object, not just the two extra fields. Every consumer of getEvents(), getEventById(), and getEventsByCommunity() is trusting a shape the compiler was told not to verify — so a genuinely malformed document reaches the render tree unflagged rather than failing at the boundary. A document created before author was written, or by a script that skips it, will pass straight through these casts and crash whichever surface dereferences event.author.

The casts also make author unreachable through the type: no consumer can display the event organiser without adding a cast of its own.

Suggested fix

  1. Add both fields to Event in src/lib/types.ts, matching the shape Question already uses at :37-38. Make them optional only if documents genuinely predate the write; if so, prefer author?: ... plus a guard at the render sites over a cast.
  2. Replace the three casts at eventService.ts:51,70,90 with a single narrowing helper, e.g. mapEventDoc(docSnap): Event, that validates the required fields and returns a properly typed object. All three call sites do identical mapping today.
  3. Confirm searchService.ts:150-164 type-checks without change once createdAt is declared, and that TS2353 is gone from npm run typecheck.
  4. Decide what should happen for a document missing author — skip it, or substitute a placeholder — and encode that in the helper rather than leaving it to whichever component dereferences it first.

Note: #23 proposes narrowing the stored author to uid/displayName/photoURL, so coordinate the field's type with that issue rather than adding a full UserProfile here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions