Add type definitions (#140)

* Add type definitions

* Fix README.md
diff --git a/README.md b/README.md
index c9bf278..2059a6f 100644
--- a/README.md
+++ b/README.md
@@ -56,12 +56,6 @@
 $ npm install pulsar-client
 ```
 
-## Typescript Definitions
-
-```shell
-$ npm install @types/pulsar-client --save-dev
-```
-
 ## Sample code
 
 Please refer to [examples](https://github.com/apache/pulsar-client-node/tree/master/examples).
diff --git a/index.d.ts b/index.d.ts
new file mode 100644
index 0000000..22901f8
--- /dev/null
+++ b/index.d.ts
@@ -0,0 +1,168 @@
+/// <reference types="node" />
+
+export interface ClientConfig {
+  serviceUrl: string;
+  authentication?: AuthenticationTls | AuthenticationAthenz | AuthenticationToken;
+  operationTimeoutSeconds?: number;
+  ioThreads?: number;
+  messageListenerThreads?: number;
+  concurrentLookupRequest?: number;
+  useTls?: boolean;
+  tlsTrustCertsFilePath?: string;
+  tlsValidateHostname?: boolean;
+  tlsAllowInsecureConnection?: boolean;
+  statsIntervalInSeconds?: number;
+  log?: (level: LogLevel, file: string, line: number, message: string) => void;
+}
+
+export class Client {
+  constructor(config: ClientConfig);
+  createProducer(config: ProducerConfig): Promise<Producer>;
+  subscribe(config: ConsumerConfig): Promise<Consumer>;
+  createReader(config: ReaderConfig): Promise<Reader>;
+  close(): Promise<null>;
+}
+
+export interface ProducerConfig {
+  topic: string;
+  producerName?: string;
+  sendTimeoutMs?: number;
+  initialSequenceId?: number;
+  maxPendingMessages?: number;
+  maxPendingMessagesAcrossPartitions?: number;
+  blockIfQueueFull?: boolean;
+  messageRoutingMode?: MessageRoutingMode;
+  hashingScheme?: HashingScheme;
+  compressionType?: CompressionType;
+  batchingEnabled?: boolean;
+  batchingMaxPublishDelayMs?: number;
+  batchingMaxMessages?: number;
+  properties?: { [key: string]: string };
+}
+
+export class Producer {
+  send(message: ProducerMessage): Promise<MessageId>;
+  flush(): Promise<null>;
+  close(): Promise<null>;
+  getProducerName(): string;
+  getTopic(): string;
+}
+
+export interface ConsumerConfig {
+  topic?: string;
+  topics?: string[];
+  topicsPattern?: string;
+  subscription: string;
+  subscriptionType?: SubscriptionType;
+  subscriptionInitialPosition?: InitialPosition;
+  ackTimeoutMs?: number;
+  nAckRedeliverTimeoutMs?: number;
+  receiverQueueSize?: number;
+  receiverQueueSizeAcrossPartitions?: number;
+  consumerName?: string;
+  properties?: { [key: string]: string };
+  listener?: (message: Message, consumer: Consumer) => void;
+  readCompacted?: boolean;
+}
+
+export class Consumer {
+  receive(timeout?: number): Promise<Message>;
+  acknowledge(message: Message): void;
+  acknowledgeId(messageId: MessageId): void;
+  negativeAcknowledge(message: Message): void;
+  negativeAcknowledgeId(messageId: MessageId): void;
+  acknowledgeCumulative(message: Message): void;
+  acknowledgeCumulativeId(messageId: MessageId): void;
+  close(): Promise<null>;
+  unsubscribe(): Promise<null>;
+}
+
+export interface ReaderConfig {
+  topic: string;
+  startMessageId: MessageId;
+  receiverQueueSize?: number;
+  readerName?: string;
+  subscriptionRolePrefix?: string;
+  readCompacted?: boolean;
+}
+
+export class Reader {
+  readNext(timeout?: number): Promise<Message>;
+  hasNext(): boolean;
+  close(): Promise<null>;
+}
+
+export interface ProducerMessage {
+  data: Buffer;
+  properties?: { [key: string]: string };
+  eventTimestamp?: number;
+  sequenceId?: number;
+  partitionKey?: string;
+  replicationClusters?: string[];
+  deliverAfter?: number;
+  deliverAt?: number;
+}
+
+export class Message {
+  getTopicName(): string;
+  getProperties(): { [key: string]: string };
+  getData(): Buffer;
+  getMessageId(): MessageId;
+  getPublishTimestamp(): number;
+  getEventTimestamp(): number;
+  getRedeliveryCount(): number;
+  getPartitionKey(): string;
+}
+
+export class MessageId {
+  static earliest(): MessageId;
+  static latest(): MessageId;
+  static deserialize(data: Buffer): MessageId;
+  serialize(): Buffer;
+  toString(): string;
+}
+
+export class AuthenticationTls {
+  constructor(params: { certificatePath: string, privateKeyPath: string });
+}
+
+export class AuthenticationAthenz {
+  constructor(params: string);
+}
+
+export class AuthenticationToken {
+  constructor(params: { token: string });
+}
+
+export enum LogLevel {
+  DEBUG = 0,
+  INFO = 1,
+  WARN = 2,
+  ERROR = 3,
+}
+
+export type MessageRoutingMode =
+  'UseSinglePartition' |
+  'RoundRobinDistribution' |
+  'CustomPartition';
+
+export type HashingScheme =
+  'Murmur3_32Hash' |
+  'BoostHash' |
+  'JavaStringHash';
+
+export type CompressionType =
+  'Zlib' |
+  'LZ4' |
+  'ZSTD' |
+  'SNAPPY';
+
+export type SubscriptionType =
+  'Exclusive' |
+  'Shared' |
+  'KeyShared' |
+  'Failover';
+
+export type InitialPosition =
+  'Latest' |
+  'Earliest';
diff --git a/package-lock.json b/package-lock.json
index dc26e73..8fd120e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -379,6 +379,58 @@
         "minimist": "^1.2.0"
       }
     },
+    "@definitelytyped/header-parser": {
+      "version": "0.0.66",
+      "resolved": "https://registry.npmjs.org/@definitelytyped/header-parser/-/header-parser-0.0.66.tgz",
+      "integrity": "sha512-7OW3yyZETfOrbseU2WhiFD9XEue5I/iAgXe9FG4rs1USD2rmB+RVxTLQVJ4kmtgGy+QrR6fJS1/cs8LgGaZh6Q==",
+      "dev": true,
+      "requires": {
+        "@definitelytyped/typescript-versions": "^0.0.66",
+        "@types/parsimmon": "^1.10.1",
+        "parsimmon": "^1.13.0"
+      }
+    },
+    "@definitelytyped/typescript-versions": {
+      "version": "0.0.66",
+      "resolved": "https://registry.npmjs.org/@definitelytyped/typescript-versions/-/typescript-versions-0.0.66.tgz",
+      "integrity": "sha512-zm6ypaRWaps+734OlgbtNUdl2VlbDg+lgm1ZiiVZu7QpuCcCMfiyanJL0uQESPaoh2VkbHQbRP6gDugFpMKh6g==",
+      "dev": true
+    },
+    "@definitelytyped/utils": {
+      "version": "0.0.66",
+      "resolved": "https://registry.npmjs.org/@definitelytyped/utils/-/utils-0.0.66.tgz",
+      "integrity": "sha512-J5/SNb0cISss1DIso7++ngzZ5EYdnosvjUgyHueQGRhnoV/jdLqtIlI4RDsk08CkeAG7V9PyIz0fA715DvogCw==",
+      "dev": true,
+      "requires": {
+        "@definitelytyped/typescript-versions": "^0.0.66",
+        "@types/node": "^12.12.29",
+        "charm": "^1.0.2",
+        "fs-extra": "^8.1.0",
+        "fstream": "^1.0.12",
+        "npm-registry-client": "^8.6.0",
+        "tar": "^2.2.2",
+        "tar-stream": "^2.1.4"
+      },
+      "dependencies": {
+        "@types/node": {
+          "version": "12.19.16",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.16.tgz",
+          "integrity": "sha512-7xHmXm/QJ7cbK2laF+YYD7gb5MggHIIQwqyjin3bpEGiSuvScMQ5JZZXPvRipi1MwckTQbJZROMns/JxdnIL1Q==",
+          "dev": true
+        },
+        "tar": {
+          "version": "2.2.2",
+          "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
+          "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
+          "dev": true,
+          "requires": {
+            "block-stream": "*",
+            "fstream": "^1.0.12",
+            "inherits": "2"
+          }
+        }
+      }
+    },
     "@eslint/eslintrc": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz",
@@ -1036,9 +1088,9 @@
       "dev": true
     },
     "@types/node": {
-      "version": "14.10.1",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.1.tgz",
-      "integrity": "sha512-aYNbO+FZ/3KGeQCEkNhHFRIzBOUgc7QvcVNKXbfnhDkSfwUv91JsQQa10rDgKSTSLkXZ1UIyPe4FJJNVgw1xWQ==",
+      "version": "14.14.25",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz",
+      "integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ==",
       "dev": true
     },
     "@types/normalize-package-data": {
@@ -1047,6 +1099,12 @@
       "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
       "dev": true
     },
+    "@types/parsimmon": {
+      "version": "1.10.6",
+      "resolved": "https://registry.npmjs.org/@types/parsimmon/-/parsimmon-1.10.6.tgz",
+      "integrity": "sha512-FwAQwMRbkhx0J6YELkwIpciVzCcgEqXEbIrIn3a2P5d3kGEHQ3wVhlN3YdVepYP+bZzCYO6OjmD4o9TGOZ40rA==",
+      "dev": true
+    },
     "@types/prettier": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.0.tgz",
@@ -1357,6 +1415,59 @@
       "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz",
       "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA=="
     },
+    "babel-code-frame": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.1.3",
+        "esutils": "^2.0.2",
+        "js-tokens": "^3.0.2"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "has-ansi": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+          "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "js-tokens": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+          "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
     "babel-jest": {
       "version": "26.3.0",
       "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.3.0.tgz",
@@ -1517,6 +1628,45 @@
         "file-uri-to-path": "1.0.0"
       }
     },
+    "bl": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz",
+      "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==",
+      "dev": true,
+      "requires": {
+        "buffer": "^5.5.0",
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.4.0"
+      },
+      "dependencies": {
+        "inherits": {
+          "version": "2.0.4",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+          "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
+    "block-stream": {
+      "version": "0.0.9",
+      "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+      "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+      "dev": true,
+      "requires": {
+        "inherits": "~2.0.0"
+      }
+    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1570,12 +1720,34 @@
         "node-int64": "^0.4.0"
       }
     },
+    "buffer": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+      "dev": true,
+      "requires": {
+        "base64-js": "^1.3.1",
+        "ieee754": "^1.1.13"
+      }
+    },
     "buffer-from": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
       "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
       "dev": true
     },
+    "builtin-modules": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+      "dev": true
+    },
+    "builtins": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz",
+      "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
+      "dev": true
+    },
     "cache-base": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
@@ -1677,6 +1849,15 @@
       "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
       "dev": true
     },
+    "charm": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/charm/-/charm-1.0.2.tgz",
+      "integrity": "sha1-it02cVOm2aWBMxBSxAkJkdqZXjU=",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1"
+      }
+    },
     "chownr": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
@@ -1829,6 +2010,12 @@
         "delayed-stream": "~1.0.0"
       }
     },
+    "command-exists": {
+      "version": "1.2.9",
+      "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
+      "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==",
+      "dev": true
+    },
     "commander": {
       "version": "6.1.0",
       "resolved": "https://registry.npmjs.org/commander/-/commander-6.1.0.tgz",
@@ -1846,6 +2033,18 @@
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
+    "concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      }
+    },
     "confusing-browser-globals": {
       "version": "1.0.9",
       "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz",
@@ -2085,6 +2284,12 @@
         "wrappy": "1"
       }
     },
+    "diff": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+      "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+      "dev": true
+    },
     "diff-sequences": {
       "version": "26.3.0",
       "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.3.0.tgz",
@@ -2134,6 +2339,67 @@
         }
       }
     },
+    "dts-critic": {
+      "version": "3.3.4",
+      "resolved": "https://registry.npmjs.org/dts-critic/-/dts-critic-3.3.4.tgz",
+      "integrity": "sha512-OjLTrSBCFbi1tDAiOXcP7G20W3HI3eIzkpSpLwvH7oDFZYdqFCMe9lsNhMZFXqsNcSTpRg3+PBS4fF27+h1qew==",
+      "dev": true,
+      "requires": {
+        "@definitelytyped/header-parser": "^0.0.66",
+        "command-exists": "^1.2.8",
+        "rimraf": "^3.0.2",
+        "semver": "^6.2.0",
+        "tmp": "^0.2.1",
+        "yargs": "^15.3.1"
+      },
+      "dependencies": {
+        "rimraf": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+          "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+          "dev": true,
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        },
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
+      }
+    },
+    "dtslint": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/dtslint/-/dtslint-4.0.6.tgz",
+      "integrity": "sha512-bj5EaTeAqVXDHo/ut8oTRN/hZNTVKTAsNkavyH/T7XeDU/bqrctlYJmQo2HWJzPDoNCjq6NdVgvOnmQBGmSHsg==",
+      "dev": true,
+      "requires": {
+        "@definitelytyped/header-parser": "^0.0.66",
+        "@definitelytyped/typescript-versions": "^0.0.66",
+        "@definitelytyped/utils": "^0.0.66",
+        "dts-critic": "^3.3.4",
+        "fs-extra": "^6.0.1",
+        "json-stable-stringify": "^1.0.1",
+        "strip-json-comments": "^2.0.1",
+        "tslint": "5.14.0",
+        "yargs": "^15.1.0"
+      },
+      "dependencies": {
+        "fs-extra": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz",
+          "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "jsonfile": "^4.0.0",
+            "universalify": "^0.1.0"
+          }
+        }
+      }
+    },
     "ecc-jsbn": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -3083,6 +3349,12 @@
         "map-cache": "^0.2.2"
       }
     },
+    "fs-constants": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+      "dev": true
+    },
     "fs-extra": {
       "version": "8.1.0",
       "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@@ -3122,6 +3394,29 @@
       "dev": true,
       "optional": true
     },
+    "fstream": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "inherits": "~2.0.0",
+        "mkdirp": ">=0.5 0",
+        "rimraf": "2"
+      },
+      "dependencies": {
+        "mkdirp": {
+          "version": "0.5.5",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+          "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+          "dev": true,
+          "requires": {
+            "minimist": "^1.2.5"
+          }
+        }
+      }
+    },
     "function-bind": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -3608,6 +3903,12 @@
         "safer-buffer": ">= 2.1.2 < 3"
       }
     },
+    "ieee754": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+      "dev": true
+    },
     "ignore": {
       "version": "4.0.6",
       "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
@@ -5042,6 +5343,15 @@
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
       "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
     },
+    "json-stable-stringify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+      "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+      "dev": true,
+      "requires": {
+        "jsonify": "~0.0.0"
+      }
+    },
     "json-stable-stringify-without-jsonify": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
@@ -5071,6 +5381,12 @@
         "graceful-fs": "^4.1.6"
       }
     },
+    "jsonify": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+      "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
+      "dev": true
+    },
     "jsprim": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -5820,6 +6136,26 @@
       "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
       "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
     },
+    "npm-package-arg": {
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz",
+      "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==",
+      "dev": true,
+      "requires": {
+        "hosted-git-info": "^2.7.1",
+        "osenv": "^0.1.5",
+        "semver": "^5.6.0",
+        "validate-npm-package-name": "^3.0.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
+      }
+    },
     "npm-packlist": {
       "version": "1.4.8",
       "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
@@ -5830,6 +6166,34 @@
         "npm-normalize-package-bin": "^1.0.1"
       }
     },
+    "npm-registry-client": {
+      "version": "8.6.0",
+      "resolved": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-8.6.0.tgz",
+      "integrity": "sha512-Qs6P6nnopig+Y8gbzpeN/dkt+n7IyVd8f45NTMotGk6Qo7GfBmzwYx6jRLoOOgKiMnaQfYxsuyQlD8Mc3guBhg==",
+      "dev": true,
+      "requires": {
+        "concat-stream": "^1.5.2",
+        "graceful-fs": "^4.1.6",
+        "normalize-package-data": "~1.0.1 || ^2.0.0",
+        "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0",
+        "npmlog": "2 || ^3.1.0 || ^4.0.0",
+        "once": "^1.3.3",
+        "request": "^2.74.0",
+        "retry": "^0.10.0",
+        "safe-buffer": "^5.1.1",
+        "semver": "2 >=2.2.1 || 3.x || 4 || 5",
+        "slide": "^1.1.3",
+        "ssri": "^5.2.4"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
+      }
+    },
     "npm-run-path": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@@ -6172,6 +6536,12 @@
       "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
       "dev": true
     },
+    "parsimmon": {
+      "version": "1.16.0",
+      "resolved": "https://registry.npmjs.org/parsimmon/-/parsimmon-1.16.0.tgz",
+      "integrity": "sha512-tekGDz2Lny27SQ/5DzJdIK0lqsWwZ667SCLFIDCxaZM7VNgQjyKLbaL7FYPKpbjdxNAXFV/mSxkq5D2fnkW4pA==",
+      "dev": true
+    },
     "pascalcase": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
@@ -6670,6 +7040,12 @@
       "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
       "dev": true
     },
+    "retry": {
+      "version": "0.10.1",
+      "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz",
+      "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=",
+      "dev": true
+    },
     "reusify": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
@@ -7092,6 +7468,15 @@
         "tweetnacl": "~0.14.0"
       }
     },
+    "ssri": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz",
+      "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "^5.1.1"
+      }
+    },
     "stack-utils": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.2.tgz",
@@ -7375,6 +7760,32 @@
         "yallist": "^4.0.0"
       }
     },
+    "tar-stream": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+      "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+      "dev": true,
+      "requires": {
+        "bl": "^4.0.3",
+        "end-of-stream": "^1.4.1",
+        "fs-constants": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^3.1.1"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
     "terminal-link": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
@@ -7408,6 +7819,26 @@
       "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
       "dev": true
     },
+    "tmp": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
+      "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+      "dev": true,
+      "requires": {
+        "rimraf": "^3.0.0"
+      },
+      "dependencies": {
+        "rimraf": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+          "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+          "dev": true,
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        }
+      }
+    },
     "tmpl": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
@@ -7498,6 +7929,76 @@
         "strip-bom": "^3.0.0"
       }
     },
+    "tslib": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+      "dev": true
+    },
+    "tslint": {
+      "version": "5.14.0",
+      "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.14.0.tgz",
+      "integrity": "sha512-IUla/ieHVnB8Le7LdQFRGlVJid2T/gaJe5VkjzRVSRR6pA2ODYrnfR1hmxi+5+au9l50jBwpbBL34txgv4NnTQ==",
+      "dev": true,
+      "requires": {
+        "babel-code-frame": "^6.22.0",
+        "builtin-modules": "^1.1.1",
+        "chalk": "^2.3.0",
+        "commander": "^2.12.1",
+        "diff": "^3.2.0",
+        "glob": "^7.1.1",
+        "js-yaml": "^3.7.0",
+        "minimatch": "^3.0.4",
+        "mkdirp": "^0.5.1",
+        "resolve": "^1.3.2",
+        "semver": "^5.3.0",
+        "tslib": "^1.8.0",
+        "tsutils": "^2.29.0"
+      },
+      "dependencies": {
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
+        "commander": {
+          "version": "2.20.3",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+          "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+          "dev": true
+        },
+        "mkdirp": {
+          "version": "0.5.5",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+          "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+          "dev": true,
+          "requires": {
+            "minimist": "^1.2.5"
+          }
+        },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
+      }
+    },
+    "tsutils": {
+      "version": "2.29.0",
+      "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
+      "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.8.1"
+      }
+    },
     "tunnel-agent": {
       "version": "0.6.0",
       "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -7532,6 +8033,12 @@
       "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
       "dev": true
     },
+    "typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+      "dev": true
+    },
     "typedarray-to-buffer": {
       "version": "3.1.5",
       "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
@@ -7541,6 +8048,12 @@
         "is-typedarray": "^1.0.0"
       }
     },
+    "typescript": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
+      "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==",
+      "dev": true
+    },
     "unc-path-regex": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
@@ -7695,6 +8208,15 @@
         "spdx-expression-parse": "^3.0.0"
       }
     },
+    "validate-npm-package-name": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
+      "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=",
+      "dev": true,
+      "requires": {
+        "builtins": "^1.0.3"
+      }
+    },
     "verror": {
       "version": "1.10.0",
       "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
diff --git a/package.json b/package.json
index 816b7c4..ef5997e 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,7 @@
   "version": "1.3.0-rc.0",
   "description": "Pulsar Node.js client",
   "main": "index.js",
+  "types": "index.d.ts",
   "directories": {
     "src": "src",
     "example": "examples"
@@ -13,6 +14,7 @@
     "configure": "node-gyp configure",
     "lint": "clang-format-lint src/*.cc src/*.h && eslint --ext .js .",
     "format": "clang-format-lint --fix src/*.cc src/*.h && eslint --fix --ext .js .",
+    "dtslint": "dtslint .",
     "build": "npm run format && node-gyp rebuild",
     "build:debug": "npm run format && node-gyp rebuild --debug",
     "license:report": "mkdir -p report && grunt grunt-license-report",
@@ -31,9 +33,11 @@
   },
   "devDependencies": {
     "@seadub/clang-format-lint": "0.0.2",
+    "@types/node": "^14.14.25",
     "clang-format": "^1.4.0",
     "commander": "^6.1.0",
     "delay": "^4.4.0",
+    "dtslint": "^4.0.6",
     "eslint": "^7.8.1",
     "eslint-config-airbnb-base": "^14.2.0",
     "eslint-plugin-import": "^2.22.0",
@@ -42,7 +46,8 @@
     "hdr-histogram-js": "^2.0.1",
     "jest": "^26.4.2",
     "license-check-and-add": "^3.0.4",
-    "lodash": "^4.17.20"
+    "lodash": "^4.17.20",
+    "typescript": "^4.1.3"
   },
   "dependencies": {
     "bindings": "^1.5.0",
diff --git a/run-unit-tests.sh b/run-unit-tests.sh
index 5e2994f..1033755 100755
--- a/run-unit-tests.sh
+++ b/run-unit-tests.sh
@@ -37,7 +37,7 @@
 apt install $PULSAR_PKG_DIR/apache-pulsar-client*.deb
 
 ./pulsar-test-service-start.sh
-npm install && npm run lint && npm run build && npm run test
+npm install && npm run lint && npm run dtslint && npm run build && npm run test
 RES=$?
 ./pulsar-test-service-stop.sh
 
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..13413c7
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,22 @@
+{
+  "compilerOptions": {
+    "target": "ES2015",
+    "lib": [
+      "ES2015"
+    ],
+    "module": "commonjs",
+    "noImplicitAny": true,
+    "noImplicitThis": true,
+    "noImplicitReturns": true,
+    "strictNullChecks": true,
+    "strictFunctionTypes": true,
+    "strictBindCallApply": true,
+    "strictPropertyInitialization": true,
+    "types": [],
+    "forceConsistentCasingInFileNames": true
+  },
+  "files": [
+    "index.d.ts",
+    "tstest.ts"
+  ]
+}
diff --git a/tslint.json b/tslint.json
new file mode 100644
index 0000000..c4c3a27
--- /dev/null
+++ b/tslint.json
@@ -0,0 +1,7 @@
+{
+  "extends": "dtslint/dtslint.json",
+  "rules": {
+    "no-unnecessary-class": false,
+    "no-relative-import-in-test": false
+  }
+}
diff --git a/tstest.ts b/tstest.ts
new file mode 100644
index 0000000..273346c
--- /dev/null
+++ b/tstest.ts
@@ -0,0 +1,267 @@
+import Pulsar = require('./index');
+
+// Maximum parameters
+(async () => {
+  const authTls: Pulsar.AuthenticationTls = new Pulsar.AuthenticationTls({
+    certificatePath: '/path/to/cert.pem',
+    privateKeyPath: '/path/to/key.pem',
+  });
+
+  const authAthenz: Pulsar.AuthenticationAthenz = new Pulsar.AuthenticationAthenz('{}');
+
+  const authToken: Pulsar.AuthenticationToken = new Pulsar.AuthenticationToken({
+    token: 'foobar',
+  });
+
+  const client: Pulsar.Client = new Pulsar.Client({
+    serviceUrl: 'pulsar://localhost:6650',
+    authentication: authToken,
+    operationTimeoutSeconds: 30,
+    ioThreads: 4,
+    messageListenerThreads: 4,
+    concurrentLookupRequest: 100,
+    useTls: false,
+    tlsTrustCertsFilePath: '/path/to/ca-cert.pem',
+    tlsValidateHostname: false,
+    tlsAllowInsecureConnection: false,
+    statsIntervalInSeconds: 60,
+    log: (level: Pulsar.LogLevel, file: string, line: number, message: string) => {
+      switch (level) {
+        case Pulsar.LogLevel.DEBUG:
+          console.log(`[DEBUG] ${message}`);
+          break;
+        case Pulsar.LogLevel.INFO:
+          console.log(`[INFO] ${message}`);
+          break;
+        case Pulsar.LogLevel.WARN:
+          console.log(`[WARN] ${message}`);
+          break;
+        case Pulsar.LogLevel.ERROR:
+          console.log(`[ERROR] ${message}`);
+          break;
+      }
+    },
+  });
+
+  const producer1: Pulsar.Producer = await client.createProducer({
+    topic: 'persistent://public/default/my-topic',
+    producerName: 'producer1',
+    sendTimeoutMs: 10000,
+    initialSequenceId: 1,
+    maxPendingMessages: 100,
+    maxPendingMessagesAcrossPartitions: 1000,
+    blockIfQueueFull: false,
+    messageRoutingMode: 'UseSinglePartition',
+    hashingScheme: 'Murmur3_32Hash',
+    compressionType: 'Zlib',
+    batchingEnabled: false,
+    batchingMaxPublishDelayMs: 50,
+    batchingMaxMessages: 100,
+    properties: {
+      key1: 'value1',
+      key2: 'value2',
+    },
+  });
+
+  const producer2: Pulsar.Producer = await client.createProducer({
+    topic: 'persistent://public/default/my-topic',
+    messageRoutingMode: 'RoundRobinDistribution',
+    hashingScheme: 'BoostHash',
+    compressionType: 'LZ4',
+  });
+
+  const producer3: Pulsar.Producer = await client.createProducer({
+    topic: 'persistent://public/default/my-topic',
+    messageRoutingMode: 'CustomPartition',
+    hashingScheme: 'JavaStringHash',
+    compressionType: 'ZSTD',
+  });
+
+  const producer4: Pulsar.Producer = await client.createProducer({
+    topic: 'persistent://public/default/my-topic',
+    compressionType: 'SNAPPY',
+  });
+
+  const consumer1: Pulsar.Consumer = await client.subscribe({
+    topic: 'persistent://public/default/my-topic',
+    subscription: 'my-sub1',
+    subscriptionType: 'Exclusive',
+    subscriptionInitialPosition: 'Latest',
+    ackTimeoutMs: 3000,
+    nAckRedeliverTimeoutMs: 5000,
+    receiverQueueSize: 1000,
+    receiverQueueSizeAcrossPartitions: 5000,
+    consumerName: 'consumer1',
+    properties: {
+      key1: 'value1',
+      key2: 'value2',
+    },
+    readCompacted: false,
+  });
+
+  const consumer2: Pulsar.Consumer = await client.subscribe({
+    topic: 'persistent://public/default/my-topic',
+    subscription: 'my-sub2',
+    subscriptionType: 'Shared',
+    subscriptionInitialPosition: 'Earliest',
+  });
+
+  const consumer3: Pulsar.Consumer = await client.subscribe({
+    topic: 'persistent://public/default/my-topic',
+    subscription: 'my-sub3',
+    subscriptionType: 'KeyShared',
+    listener: (message: Pulsar.Message, consumer: Pulsar.Consumer) => {
+    },
+  });
+
+  const consumer4: Pulsar.Consumer = await client.subscribe({
+    topic: 'persistent://public/default/my-topic',
+    subscription: 'my-sub4',
+    subscriptionType: 'Failover',
+  });
+
+  const reader1: Pulsar.Reader = await client.createReader({
+    topic: 'persistent://public/default/my-topic',
+    startMessageId: Pulsar.MessageId.latest(),
+    receiverQueueSize: 1000,
+    readerName: 'reader1',
+    subscriptionRolePrefix: 'reader-',
+    readCompacted: false,
+  });
+
+  const reader2: Pulsar.Reader = await client.createReader({
+    topic: 'persistent://public/default/my-topic',
+    startMessageId: Pulsar.MessageId.earliest(),
+  });
+
+  const producerName: string = producer1.getProducerName();
+  const topicName1: string = producer1.getTopic();
+
+  const messageId1: Pulsar.MessageId = await producer1.send({
+    data: Buffer.from('my-message'),
+    properties: {
+      key1: 'value1',
+      key2: 'value2',
+    },
+    eventTimestamp: Date.now(),
+    sequenceId: 10,
+    partitionKey: 'key1',
+    replicationClusters: [
+      'cluster1',
+      'cluster2',
+    ],
+    deliverAfter: 30000,
+    deliverAt: Date.now() + 30000,
+  });
+
+  const messageIdString: string = messageId1.toString();
+  const messageIdBuffer: Buffer = messageId1.serialize();
+  const messageId2: Pulsar.MessageId = Pulsar.MessageId.deserialize(messageIdBuffer);
+
+  const message1: Pulsar.Message = await consumer1.receive();
+  const message2: Pulsar.Message = await consumer2.receive(1000);
+
+  consumer1.negativeAcknowledge(message1);
+  consumer1.negativeAcknowledgeId(messageId1);
+  consumer1.acknowledge(message1);
+  consumer1.acknowledgeId(messageId1);
+  consumer1.acknowledgeCumulative(message1);
+  consumer1.acknowledgeCumulativeId(messageId1);
+
+  const topicName2: string = message1.getTopicName();
+  const properties: { [key: string]: string } = message1.getProperties();
+  const messageBuffer: Buffer = message1.getData();
+  const messageId3: Pulsar.MessageId = message1.getMessageId();
+  const publishTime: number = message1.getPublishTimestamp();
+  const eventTime: number = message1.getEventTimestamp();
+  const redeliveryCount: number = message1.getRedeliveryCount();
+  const partitionKey: string = message1.getPartitionKey();
+
+  const message3: Pulsar.Message = await reader1.readNext();
+  const message4: Pulsar.Message = await reader2.readNext(1000);
+  const hasNext: boolean = reader1.hasNext();
+
+  await producer1.flush();
+  await producer1.close();
+  await producer2.close();
+  await producer3.close();
+  await producer4.close();
+  await consumer1.unsubscribe();
+  await consumer2.close();
+  await consumer3.close();
+  await consumer4.close();
+  await reader1.close();
+  await reader2.close();
+  await client.close();
+})();
+
+// Minimal parameters
+(async () => {
+  const client: Pulsar.Client = new Pulsar.Client({
+    serviceUrl: 'pulsar://localhost:6650',
+  });
+
+  const producer: Pulsar.Producer = await client.createProducer({
+    topic: 'persistent://public/default/my-topic',
+  });
+
+  const consumer1: Pulsar.Consumer = await client.subscribe({
+    topic: 'persistent://public/default/my-topic',
+    subscription: 'my-sub1',
+  });
+
+  const consumer2: Pulsar.Consumer = await client.subscribe({
+    topics: ['persistent://public/default/my-topic'],
+    subscription: 'my-sub2',
+  });
+
+  const consumer3: Pulsar.Consumer = await client.subscribe({
+    topicsPattern: 'persistent://public/default/my-topi[a-z]',
+    subscription: 'my-sub3',
+  });
+
+  const reader: Pulsar.Reader = await client.createReader({
+    topic: 'persistent://public/default/my-topic',
+    startMessageId: Pulsar.MessageId.latest(),
+  });
+
+  const messageId: Pulsar.MessageId = await producer.send({
+    data: Buffer.from('my-message'),
+  });
+
+  await producer.close();
+  await consumer1.close();
+  await consumer2.close();
+  await consumer3.close();
+  await reader.close();
+  await client.close();
+})();
+
+// Missing required parameters
+(async () => {
+  // $ExpectError
+  const client: Pulsar.Client = new Pulsar.Client({
+  });
+
+  // $ExpectError
+  const producer: Pulsar.Producer = await client.createProducer({
+  });
+
+  // $ExpectError
+  const consumer: Pulsar.Consumer = await client.subscribe({
+  });
+
+  // $ExpectError
+  const reader1: Pulsar.Reader = await client.createReader({
+    topic: 'persistent://public/default/my-topic',
+  });
+
+  // $ExpectError
+  const reader2: Pulsar.Reader = await client.createReader({
+    startMessageId: Pulsar.MessageId.latest(),
+  });
+
+  // $ExpectError
+  const messageId: Pulsar.MessageId = await producer.send({
+  });
+})();