Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript Error in Devtools: TransactionEvent #873

Open
gwbaik9717 opened this issue Jul 20, 2024 · 5 comments
Open

TypeScript Error in Devtools: TransactionEvent #873

gwbaik9717 opened this issue Jul 20, 2024 · 5 comments
Assignees

Comments

@gwbaik9717
Copy link
Contributor

Description:

There is a type-related error in the existing code within the tools/devtools/src/devtools/tabs/History.tsx directory related to TransactionEvent. The TypeScript error message is as follows:

Property 'source' does not exist on type 'DocEvent<Indexable, OperationInfo>'.

Screenshot 2024-07-20 at 10 12 18 AM

Why:

This change will help prevent potential bugs, ensure type safety, and improve overall code quality.

@gwbaik9717 gwbaik9717 changed the title Define Type for transactionEvent in Devtools Type Error in Devtools: TransactionEvent Jul 20, 2024
@gwbaik9717 gwbaik9717 changed the title Type Error in Devtools: TransactionEvent TypeScript Error in Devtools: TransactionEvent Jul 20, 2024
@chacha912 chacha912 self-assigned this Jul 22, 2024
@KimKyuHoi
Copy link
Member

KimKyuHoi commented Aug 5, 2024

@devleejb Could I give it a try? i want to challenge it

@KimKyuHoi
Copy link
Member

@gwbaik9717
The part I am concerned about is when I look at the current export type of DocEvent,

export type DocEvent<P extends Indexable = Indexable, T = OperationInfo> =
  | StatusChangedEvent
  | ConnectionChangedEvent
  | SyncStatusChangedEvent
  | SnapshotEvent
  | LocalChangeEvent<T, P>
  | RemoteChangeEvent<T, P>
  | InitializedEvent<P>
  | WatchedEvent<P>
  | UnwatchedEvent<P>
  | PresenceChangedEvent<P>;

Type 'DocEvent<Indexable, OperationInfo>' does not have property 'source' because within the DocEvent type, ConnectionChangeEvent and SyncStatusChangedEvent do not have a source property. It seems like this error occurs.

Is it correct to add a source to ConnectionChangeEvent and SyncStatusChangedEvent, or is it correct to use the type guard function in the History.tsx file to check whether it is an event type with a source property and then access it?

for example

function hasSource(event: DocEvent): event is StatusChangedEvent | LocalChangeEvent | RemoteChangeEvent {
  return 'source' in event;
}

After writing this

   const firstEvent = event.event[0];

    let source: string;
    if (hasSource(firstEvent)) {
      source = firstEvent.source;
    } else {
      source = 'unknown'; 
    }

Is it correct to display it like this?

@devleejb
Copy link
Member

devleejb commented Aug 5, 2024

@chacha912
Is there any progress?

@chacha912 chacha912 removed their assignment Aug 6, 2024
@chacha912
Copy link
Contributor

chacha912 commented Aug 6, 2024

@devleejb I tried to make this work, but I got stuck because it needed too many changes in the devtools types and other areas.

Thank you, @KimKyuHoi , for your interest.

I think we could fix this by following these steps:

  1. First, we could add source to the BaseDocEvent type. This would make sure all DocEvents have a source property. Then, we could add the source property to ConnectionChangeEvent and SyncStatusChangedEvent. This should solve the problem for now.

  2. In the future, we could make it even better like this: The main issue is that when we set up devtools, we only keep the events that devtools needs. Right now, devtools uses events that have information to rebuild the document.

if (
event.some(
(docEvent) =>
docEvent.type !== DocEventType.StatusChanged &&
docEvent.type !== DocEventType.Snapshot &&
docEvent.type !== DocEventType.LocalChange &&
docEvent.type !== DocEventType.RemoteChange &&
docEvent.type !== DocEventType.Initialized &&
docEvent.type !== DocEventType.Watched &&
docEvent.type !== DocEventType.Unwatched &&
docEvent.type !== DocEventType.PresenceChanged,
)
) {
return;
}

We could create a new type for these specific events:

 /**
  * `EventsForDocRebuild` is a list of events used to rebuild a document.
  */
 export type EventsForDocRebuild<
   P extends Indexable = Indexable,
   T = OperationInfo,
 > = Array<
   | StatusChangedEvent
   | SnapshotEvent
   | LocalChangeEvent<T, P>
   | RemoteChangeEvent<T, P>
   | InitializedEvent<P>
   | WatchedEvent<P>
   | UnwatchedEvent<P>
   | PresenceChangedEvent<P>
 >;

 /**
  * `isEventsForDocRebuild` checks if an event can be used to rebuild a document.
  */
 export function isEventsForDocRebuild(
   event: TransactionEvent,
 ): event is EventsForDocRebuild {
   const typesForDocRebuild = [
     DocEventType.StatusChanged,
     DocEventType.Snapshot,
     DocEventType.LocalChange,
     DocEventType.RemoteChange,
     DocEventType.Initialized,
     DocEventType.Watched,
     DocEventType.Unwatched,
     DocEventType.PresenceChanged,
   ];

   return event.every((docEvent) =>
     typesForDocRebuild.includes(docEvent.type),
   );
 }

This way, we can be more sure that we're using the right events for rebuilding documents, and it's easier for TypeScript to check if we're doing it correctly.
I attempted the second method, but I encountered issues with the type declaration location and importing into devtools after building, which blocked my progress. For now, I think it would be fine to proceed with the first method.

@KimKyuHoi
Copy link
Member

@chacha912
Certainly, when looking at future methods, the second method is clear. However, I think that if you choose the second method, you will have to go around a lot. Then, I'll try the first method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In progress
Development

No branches or pull requests

4 participants