From 3444791a7ed807098ab17155e8d498a915f27750 Mon Sep 17 00:00:00 2001 From: Zihua Li Date: Wed, 30 Mar 2022 10:10:25 +0800 Subject: [PATCH] fix: support TypeScript interface as parameters of hmset and mset (#1545) Closes #1536 --- bin/overrides.js | 6 +- lib/utils/RedisCommander.ts | 14 ++--- test/functional/transformer.ts | 92 ++++++++++++------------------ test/typing/transformers.test-d.ts | 51 +++++++++++++++++ 4 files changed, 93 insertions(+), 70 deletions(-) create mode 100644 test/typing/transformers.test-d.ts diff --git a/bin/overrides.js b/bin/overrides.js index 42ca1bdf..8ef4e6c5 100644 --- a/bin/overrides.js +++ b/bin/overrides.js @@ -1,7 +1,7 @@ const msetOverrides = { overwrite: false, defs: [ - "$1(object: Record, callback?: Callback<'OK'>): Result<'OK', Context>", + "$1(object: object, callback?: Callback<'OK'>): Result<'OK', Context>", "$1(map: Map, callback?: Callback<'OK'>): Result<'OK', Context>", ], }; @@ -19,14 +19,14 @@ module.exports = { hset: { overwrite: false, defs: [ - "$1(key: RedisKey, object: Record, callback?: Callback): Result", + "$1(key: RedisKey, object: object, callback?: Callback): Result", "$1(key: RedisKey, map: Map, callback?: Callback): Result", ], }, hmset: { overwrite: false, defs: [ - "$1(key: RedisKey, object: Record, callback?: Callback<'OK'>): Result<'OK', Context>", + "$1(key: RedisKey, object: object, callback?: Callback<'OK'>): Result<'OK', Context>", "$1(key: RedisKey, map: Map, callback?: Callback<'OK'>): Result<'OK', Context>", ], }, diff --git a/lib/utils/RedisCommander.ts b/lib/utils/RedisCommander.ts index 5aabbecc..0f6cbbad 100644 --- a/lib/utils/RedisCommander.ts +++ b/lib/utils/RedisCommander.ts @@ -4280,7 +4280,7 @@ interface RedisCommander { */ hmset( key: RedisKey, - object: Record, + object: object, callback?: Callback<"OK"> ): Result<"OK", Context>; hmset( @@ -4407,7 +4407,7 @@ interface RedisCommander { */ hset( key: RedisKey, - object: Record, + object: object, callback?: Callback ): Result; hset( @@ -5513,10 +5513,7 @@ interface RedisCommander { * - _complexity_: O(N) where N is the number of keys to set. * - _since_: 1.0.1 */ - mset( - object: Record, - callback?: Callback<"OK"> - ): Result<"OK", Context>; + mset(object: object, callback?: Callback<"OK">): Result<"OK", Context>; mset( map: Map, callback?: Callback<"OK"> @@ -5537,10 +5534,7 @@ interface RedisCommander { * - _complexity_: O(N) where N is the number of keys to set. * - _since_: 1.0.1 */ - msetnx( - object: Record, - callback?: Callback<"OK"> - ): Result<"OK", Context>; + msetnx(object: object, callback?: Callback<"OK">): Result<"OK", Context>; msetnx( map: Map, callback?: Callback<"OK"> diff --git a/test/functional/transformer.ts b/test/functional/transformer.ts index 50cb2d36..5685f75a 100644 --- a/test/functional/transformer.ts +++ b/test/functional/transformer.ts @@ -5,85 +5,63 @@ import { expect } from "chai"; describe("transformer", () => { describe("default transformer", () => { describe("hmset", () => { - it("should support object", (done) => { + it("should support object", async () => { const redis = new Redis(); - redis.hmset("foo", { a: 1, b: "2" }, function (err, result) { - expect(result).to.eql("OK"); - redis.hget("foo", "b", function (err, result) { - expect(result).to.eql("2"); - done(); - }); - }); + expect(await redis.hmset("foo", { a: 1, b: "2" })).to.eql("OK"); + expect(await redis.hget("foo", "b")).to.eql("2"); }); - it("should support Map", (done) => { + + it("should support Map with string keys", async () => { const redis = new Redis(); const map = new Map(); map.set("a", 1); map.set("b", "2"); - redis.hmset("foo", map, function (err, result) { - expect(result).to.eql("OK"); - redis.hget("foo", "b", function (err, result) { - expect(result).to.eql("2"); - done(); - }); - }); + map.set(42, true); + map.set(Buffer.from("buffer"), "utf8"); + map.set(Buffer.from([0xff]), "binary"); + expect(await redis.hmset("foo", map)).to.eql("OK"); + expect(await redis.hget("foo", "a")).to.eql("1"); + expect(await redis.hget("foo", "b")).to.eql("2"); + expect(await redis.hget("foo", "42")).to.eql("true"); + expect(await redis.hget("foo", "buffer")).to.eql("utf8"); + expect(await redis.hget("foo", Buffer.from([0xff]))).to.eql("binary"); }); - it("should not affect the old way", (done) => { + + it("should not affect the old way", async () => { const redis = new Redis(); - redis.hmset("foo", "a", 1, "b", "2", function (err, result) { - expect(result).to.eql("OK"); - redis.hget("foo", "b", function (err, result) { - expect(result).to.eql("2"); - done(); - }); - }); + expect(await redis.hmset("foo", "a", 1, "b", "2")).to.eql("OK"); + expect(await redis.hget("foo", "b")).to.eql("2"); }); }); describe("mset", () => { - it("should support object", (done) => { + it("should support object", async () => { const redis = new Redis(); - redis.mset({ a: 1, b: "2" }, function (err, result) { - expect(result).to.eql("OK"); - redis.mget("a", "b", function (err, result) { - expect(result).to.eql(["1", "2"]); - done(); - }); - }); + expect(await redis.mset({ a: 1, b: "2" })).to.eql("OK"); + expect(await redis.mget("a", "b")).to.eql(["1", "2"]); }); - it("should support Map", (done) => { + + it("should support Map", async () => { const redis = new Redis(); const map = new Map(); map.set("a", 1); map.set("b", "2"); - redis.mset(map, function (err, result) { - expect(result).to.eql("OK"); - redis.mget("a", "b", function (err, result) { - expect(result).to.eql(["1", "2"]); - done(); - }); - }); + expect(await redis.mset(map)).to.eql("OK"); + expect(await redis.mget("a", "b")).to.eql(["1", "2"]); }); - it("should not affect the old way", (done) => { + + it("should not affect the old way", async () => { const redis = new Redis(); - redis.mset("a", 1, "b", "2", function (err, result) { - expect(result).to.eql("OK"); - redis.mget("a", "b", function (err, result) { - expect(result).to.eql(["1", "2"]); - done(); - }); - }); + expect(await redis.mset("a", 1, "b", "2")).to.eql("OK"); + expect(await redis.mget("a", "b")).to.eql(["1", "2"]); }); - it("should work with keyPrefix option", (done) => { + + it("should work with keyPrefix option", async () => { const redis = new Redis({ keyPrefix: "foo:" }); - redis.mset({ a: 1, b: "2" }, function (err, result) { - expect(result).to.eql("OK"); - const otherRedis = new Redis(); - otherRedis.mget("foo:a", "foo:b", function (err, result) { - expect(result).to.eql(["1", "2"]); - done(); - }); - }); + expect(await redis.mset({ a: 1, b: "2" })).to.eql("OK"); + + const otherRedis = new Redis(); + expect(await otherRedis.mget("foo:a", "foo:b")).to.eql(["1", "2"]); }); }); diff --git a/test/typing/transformers.test-d.ts b/test/typing/transformers.test-d.ts new file mode 100644 index 00000000..a65b4ac0 --- /dev/null +++ b/test/typing/transformers.test-d.ts @@ -0,0 +1,51 @@ +import { expectType } from "tsd"; +import Redis from "../../built"; + +interface User { + name: string; + title: string; +} + +const user: User = { name: "Bob", title: "Engineer" }; +const stringMap = new Map([["key", "value"]]); +const numberMap = new Map([[42, "value"]]); +const bufferMap = new Map([[Buffer.from([0xff]), "value"]]); +const mixedMap = new Map([ + [Buffer.from([0xff]), "value"], + [42, "value"], + ["field", "value"], +]); + +const redis = new Redis(); + +// mset +expectType>(redis.mset("key1", "value1", "key2", "value2")); +expectType>(redis.mset(user)); +expectType>(redis.mset(stringMap)); +expectType>(redis.mset(numberMap)); +expectType>(redis.mset(bufferMap)); +expectType>(redis.mset(mixedMap)); + +// msetnx +expectType>(redis.msetnx(user)); +expectType>(redis.msetnx(stringMap)); +expectType>(redis.msetnx(numberMap)); +expectType>(redis.msetnx(bufferMap)); +expectType>(redis.msetnx(mixedMap)); + +// hmset +expectType>(redis.hmset("key", user)); +expectType>(redis.hmset("key", stringMap)); +expectType>(redis.hmset("key", numberMap)); +expectType>(redis.hmset("key", bufferMap)); +expectType>(redis.hmset("key", mixedMap)); + +// hset +expectType>(redis.hset("key", user)); +expectType>(redis.hset("key", stringMap)); +expectType>(redis.hset("key", numberMap)); +expectType>(redis.hset("key", bufferMap)); +expectType>(redis.hset("key", mixedMap)); + +// hgetall +expectType>>(redis.hgetall("key"));