Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript error when using amqplib that can't

I'm working on a Node.js project using TypeScript and the amqplib package (currently at version 0.10.5). When I try to create a connection and channel in my RabbitMQ configuration file, TypeScript throws the following errors:

  1. Property 'close' does not exist on type 'Connection'
  2. Property 'createChannel' does not exist on type 'Connection'
  3. Type 'ChannelModel' is missing the following properties from type 'Connection': serverProperties, expectSocketClose, sentSinceLastCheck, recvSinceLastCheck, sendMessage
import * as amqp from 'amqplib';
import { Connection, Channel } from 'amqplib';

export class RabbitMQConfig {
  private static connection: Connection | null = null;
  private static channel: Channel | null = null;

  public static async connect(): Promise<void> {
    if (!this.connection) {
      this.connection = await amqp.connect('amqp://localhost');
      this.channel = await this.connection.createChannel();

      this.connection.on('close', () => {
        console.error('RabbitMQ connection closed.');
      });

      this.connection.on('error', (err) => {
        console.error('RabbitMQ connection error:', err);
      });

      console.log('RabbitMQ connected and channel created successfully.');
    }
  }

  public static getChannel(): Channel {
    if (!this.channel) {
      throw new Error('RabbitMQ channel is not initialized. Call connect() first.');
    }
    return this.channel;
  }

  public static async closeConnection(): Promise<void> {
    if (this.channel) {
      await this.channel.close();
      this.channel = null;
    }
    if (this.connection) {
      await this.connection.close();
      this.connection = null;
    }
    console.log('RabbitMQ connection closed.');
  }
}

I don't know what seems to be the issue since I did try importing the correct module but TypeScript still complains that the methods close() and createChannel() do not exist on the Connection type.

Any suggestions on how to resolve this type of issue would be greatly appreciated.

like image 529
Habody.lOl Avatar asked Jul 12 '26 12:07

Habody.lOl


2 Answers

This might be a @types problem as I have just encountered the same or a similar problem updating the dependencies for a typescript project.

Updating to "@types/amqplib": "0.10.7" with "amqplib": "0.10.5" broke the build with the errors you describe.

I checked on the @types github repo in the ampqlib folder and there has been a recent commit which appears to remove the createChannel method, amongst others, from the Connection definition.

I checked on the amqp-node/amqplib github repo in the change log, examples and also on the main readme page and they all indicate that createChannel etc are available on the Connection object.

The solution in my case was to revert back to @types/amqplib v0.10.6

"@types/amqplib": "0.10.6",

Be sure to target the exact version (for now) i.e. don't use "^" otherwise you risk getting the later version.

Having done this my project now builds

like image 111
Hargrovm Avatar answered Jul 15 '26 01:07

Hargrovm


The maintainers of the typings for amqplib introduced a breaking change. The connect() method of the amqp object now returns a ChannelModel instead of a Connection. All I had to do was change the declaration for my connection to the new type and the problem was solved.

Before:

import amqp, { Connection, Channel, ConsumeMessage } from 'amqplib';

export type ConsumerCallback = (channel: Channel, message: ConsumeMessage | null) => void;

export class RabbitMQConsumer {
  _queue: string;
  _connection: Connection | null = null;
  _channel: Channel | null = null;
  _connected: boolean = false;

  public constructor(queue: string) {
    this._queue = queue;
  }

  async connect(): Promise<boolean> {
    this._connection = await amqp.connect('amqp://localhost');
    const channel = await this._connection.createChannel();
    ...
    ...

After (with quite a bit of rework on the class itself):

import { Channel, ConsumeMessage, Options, connect, ChannelModel } from 'amqplib';
import { RabbitMQConfig } from './interfaces.js';
import { cloneObject } from './utilities.js';

export type ConsumerCallback = (channel: Channel, message: ConsumeMessage | null) => void;

export class RabbitMQConsumer {
  _options: Options.Connect;
  _queuename: string;
  _connection: ChannelModel | null = null;
  _channel: Channel | null = null;
  _connected: boolean = false;

  public constructor(config: RabbitMQConfig) {
    this._options = cloneObject(config.options);
    this._queuename = config.queuename;
  }

  async connect(): Promise<boolean> {
    this._connection = await connect(this._options);
    if (!this._connection) return false;
    const channel = await this._connection.createChannel();
    if (channel) {
      ...
      ...

This is code from a minimal producer/consumer pair that I use basically as a regression test.

It's rather uncouth of the maintainers to introduce a breaking change at a patch-level commit with so little fanfare.

like image 40
David G Avatar answered Jul 15 '26 02:07

David G



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!