Skip to content

watchContractEvent log args types narrowing fail #3767

@saqlain1020

Description

@saqlain1020

Check existing issues

Viem Version

2.31.4

Current Behavior

When using watchContractEvent from PublicClient without specifying an eventName, the type inference for log.args includes unnecessary union types (Record<string, unknown> and readonly unknown[]) even after narrowing with a condition like log.eventName === "CampaignCreated".

The type of log.args remains a union type:

args: Record<string, unknown> | readonly unknown[] | {
  campaignId?: bigint | undefined;
  creator?: `0x${string}` | undefined;
}

Expected Behavior

After checking log.eventName === "CampaignCreated", TypeScript should narrow the type of log.args to only the specific event args type:

{
  campaignId?: bigint | undefined;
  creator?: `0x${string}` | undefined;
}

Steps To Reproduce

Reproduction Link

publicClient.watchContractEvent({
  abi: CampaignManagerAbi,
  address: "0x0000...,
  pollingInterval: 5000,
  onError: (e) => {
    console.log('[Listener] Error', e);
  },
  onLogs: async (logs) => {
    if (logs.length === 0) return;
    const promises = logs.map(async (log) => {
      if (log.eventName === 'CampaignCreated') {
        const { creator } = log.args; // Type error here, creator not in type
      }
    });
  },
});

Link to Minimal Reproducible Example

No response

Anything else?

Workaround 1

Specifying eventName: 'CampaignCreated' resolves the type issue, but this limits the ability to listen for multiple events in a single watcher.


Typescript Version: 5.8.3
Using Nest JS

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions