This is an automated email from the ASF dual-hosted git repository.

tbonelee pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git


The following commit(s) were added to refs/heads/master by this push:
     new def2de1cc2 [ZEPPELIN-6446] Type message listener callbacks
def2de1cc2 is described below

commit def2de1cc24e9cfb80f3d22dd2232e8f73885cc0
Author: chaeyoung kim <[email protected]>
AuthorDate: Mon Oct 5 22:30:20 2026 +0900

    [ZEPPELIN-6446] Type message listener callbacks
    
    ### What is this PR for?
    
    The message listener decorator previously required `<at>ts-ignore` when 
invoking decorated callbacks because its conditional callback type did not 
align with the received payload.
    
    This PR introduces a typed `MessageHandler<T>`, explicitly connects each 
message operation `K` to `MessageReceiveDataTypeMap[K]`, and invokes the 
callback without TypeScript suppression or broad `any` types. The existing test 
now uses the actual `<at>MessageListener` decorator syntax to verify the typed 
integration.
    
    ### What type of PR is it?
    
    Refactoring
    
    ### Todos
    
    * [x] Remove the `<at>ts-ignore` suppression
    * [x] Preserve the relationship between message operations and payload types
    * [x] Verify all existing message listeners compile
    * [x] Add coverage using the actual decorator syntax
    
    ### What is the Jira issue?
    
    https://issues.apache.org/jira/browse/ZEPPELIN-6446
    
    ### How should this be tested?
    
    ```bash
    cd zeppelin-web-angular
    npm run test:shell
    npm run lint
    npm run build:angular
    ```
    
    Results:
    
    * 167 shell unit tests passed
    * Frontend lint passed with no errors
    * Production Angular build passed
    
    ### Questions:
    
    * Does the license files need to update? No.
    * Is there breaking changes for older versions? No.
    * Does this needs documentation? No.
    
    
    Closes #5533 from chelsseeey/ZEPPELIN-6446-type-message-listener-callback.
    
    Signed-off-by: ChanHo Lee <[email protected]>
---
 .../src/app/core/message-listener/message-listener.spec.ts  |  5 +----
 .../src/app/core/message-listener/message-listener.ts       | 13 +++++++------
 2 files changed, 8 insertions(+), 10 deletions(-)

diff --git 
a/zeppelin-web-angular/src/app/core/message-listener/message-listener.spec.ts 
b/zeppelin-web-angular/src/app/core/message-listener/message-listener.spec.ts
index 7fd1778ae6..e88cc7ae56 100644
--- 
a/zeppelin-web-angular/src/app/core/message-listener/message-listener.spec.ts
+++ 
b/zeppelin-web-angular/src/app/core/message-listener/message-listener.spec.ts
@@ -70,15 +70,12 @@ describe('MessageListener', () => {
     class TestComponent extends MessageListenersManager {
       receivedData?: MessageReceiveDataTypeMap[OP.NOTE];
 
+      @MessageListener(OP.NOTE)
       handleNote(data: MessageReceiveDataTypeMap[OP.NOTE]): void {
         this.receivedData = data;
       }
     }
 
-    const descriptor = 
Object.getOwnPropertyDescriptor(TestComponent.prototype, 'handleNote')!;
-
-    MessageListener(OP.NOTE)(TestComponent.prototype, 'handleNote', 
descriptor);
-
     const component = new TestComponent(messageService);
     const data = {} as MessageReceiveDataTypeMap[OP.NOTE];
 
diff --git 
a/zeppelin-web-angular/src/app/core/message-listener/message-listener.ts 
b/zeppelin-web-angular/src/app/core/message-listener/message-listener.ts
index 93c6294700..acbba8f317 100644
--- a/zeppelin-web-angular/src/app/core/message-listener/message-listener.ts
+++ b/zeppelin-web-angular/src/app/core/message-listener/message-listener.ts
@@ -34,7 +34,7 @@ export class MessageListenersManager implements OnDestroy {
   }
 }
 
-type ListenerArgumentsType<T> = T extends undefined ? () => void : (data: T) 
=> void;
+type MessageHandler<T> = (data: T) => void;
 
 const createMessageListener = <K extends keyof MessageReceiveDataTypeMap, T>(
   op: K,
@@ -43,9 +43,9 @@ const createMessageListener = <K extends keyof 
MessageReceiveDataTypeMap, T>(
   return function (
     target: MessageListenersManager,
     propertyKey: string,
-    descriptor: TypedPropertyDescriptor<ListenerArgumentsType<T>>
+    descriptor: TypedPropertyDescriptor<MessageHandler<T>>
   ) {
-    const oldValue = descriptor.value as ListenerArgumentsType<T>;
+    const oldValue = descriptor.value!;
 
     const fn = function (this: MessageListenersManager) {
       if (!this.__zeppelinMessageListeners$__) {
@@ -55,8 +55,7 @@ const createMessageListener = <K extends keyof 
MessageReceiveDataTypeMap, T>(
       this.__zeppelinMessageListeners$__.add(
         receiver(this.messageService, op).subscribe(data => {
           try {
-            // @ts-ignore
-            oldValue.apply(this, [data]);
+            oldValue.call(this, data);
           } catch (error) {
             console.error(`Failed to handle WebSocket OP ${String(op)}`, 
error);
             throw error;
@@ -76,7 +75,9 @@ const createMessageListener = <K extends keyof 
MessageReceiveDataTypeMap, T>(
 };
 
 export const MessageListener = <K extends keyof MessageReceiveDataTypeMap>(op: 
K) => {
-  return createMessageListener(op, (messageService, targetOp) => 
messageService.receive(targetOp));
+  return createMessageListener<K, MessageReceiveDataTypeMap[K]>(op, 
(messageService, targetOp) =>
+    messageService.receive(targetOp)
+  );
 };
 
 export const MessageEnvelopeListener = <K extends keyof 
MessageReceiveDataTypeMap>(op: K) => {

Reply via email to