fix: search for invitation in members table by rsbh · Pull Request #1457 · raystack/frontier
9-9: Type relaxation may break downstream type safety.
Changing MemberWithInvite to Partial<User> & Partial<Invitation> makes all fields optional, including id which is required for actual users. Downstream consumers (e.g., MembersActions accessing member.id for policy queries) lose compile-time guarantees that id exists for non-invitation members.
Consider a discriminated union to preserve type safety:
♻️ Suggested type definition
-export type MemberWithInvite = Partial<User> & Partial<Invitation> & { invited?: boolean }; +export type MemberWithInvite = + | (User & { invited?: false }) + | (Invitation & { email: string; invited: true });
77-86: The email mapping is correct; consider removing the unsafe cast.
The logic to map userId to email for invitations correctly addresses the search issue. However, the as unknown as MemberWithInvite[] cast bypasses type checking entirely.
If the type definition is adjusted to a discriminated union (as suggested above), this cast becomes unnecessary and the code gains full type safety:
♻️ Suggested refactor
const updatedUsers = useMemo(() => {
- const invitations = (invitationsData?.invitations || []).map(user => {
- return {
- ...user,
- email: user.userId,
- invited: true
- };
- });
- return [...users, ...invitations] as unknown as MemberWithInvite[];
+ const invitations: MemberWithInvite[] = (invitationsData?.invitations || []).map(inv => ({
+ ...inv,
+ email: inv.userId,
+ invited: true as const
+ }));
+ const userMembers: MemberWithInvite[] = users.map(u => ({ ...u, invited: false as const }));
+ return [...userMembers, ...invitations];
}, [users, invitationsData?.invitations]);