英文:
Nodejs + Typescript + RedisJSON
问题
I just started programming a little bit with nodejs, typescript and redis.
Unfortunately I run into a problem with redis:
I define an interface of data to be stored in redis. However, as soon as I write the type behind the variable redis complains to me.
Same when i get Keys from redis: How to tell Typescript which type the data is?
Example:
async function RedisQuestion() {
const redis = createClient();
interface userLogins {
token: string;
active: boolean;
}
interface myUser {
name: string;
id: string;
logins: userLogins[];
}
const objToStore: myUser = {
name: "Karl Mustermann",
id: "1",
logins: [
{
token: "1234",
active: true
},
{
token: "2345",
active: false
}
]
};
await redis.json.set("key", "$", objToStore);
const redisResult = redis.json.get("key") as myUser;
console.log(redisUser);
}
The way it works is if i say
await redis.json.set("key", "$", objToStore as any);
And if i get values from redis:
await redis.json.get("key") as any as myUser;
But there must be a better way?! Hope you can help
Thanks a lot
英文:
I just started programming a little bit with nodejs, typescript and redis.
Unfortunately I run into a problem with redis:
I define an interface of data to be stored in redis. However, as soon as I write the type behind the variable redis complains to me.
Same when i get Keys from redis: How to tell Typescript which type the data is?
Example:
async function RedisQuestion() {
const redis = createClient();
interface userLogins {
token: string;
active: boolean;
}
interface myUser {
name: string;
id: string;
logins: userLogins[];
}
const objToStore: myUser = {
name: "Karl Mustermann",
id: "1",
logins: [
{
token: "1234",
active: true
},
{
token: "2345",
active: false
}
]
};
await redis.json.set("key", "$", objToStore);
const redisResult = redis.json.get("key") as myUser;
console.log(redisUser);
}
The way it works is if i say
await redis.json.set("key", "$", objToStore as any);
And if i get values from redis:
await redis.json.get("key") as any as myUser;
But there must be a better way?! Hope you can help
Thanks a lot
答案1
得分: 3
RedisJSON 类型声明要求您提供的 JSON 对象具有索引签名声明。您的 myUser
接口没有这个声明,因此它们不兼容。您需要使用类型(下面会详细说明)而不是接口,或者在接口声明中显式包含索引签名。
以下代码有效:
type UserLogins = {
token: string;
active: boolean;
}
type MyUser = {
name: string;
id: string;
logins: UserLogins[];
}
async function redisQuestion() {
const redis = createClient();
const objToStore: MyUser = {
name: 'Karl Mustermann',
id: '1',
logins: [],
};
await redis.json.set('key', '$', objToStore);
// 您可以在此处使用类型断言来告诉 TypeScript GET 将返回哪种类型。
// 您应该包含 'null' 来强制您检查空结果并防止运行时错误。
const redisUser = await redis.json.get('key') as MyUser | null;
console.log(redisUser);
}
代码提供的解释:
您提供的代码引发以下 TypeScript 错误:
类型 'myUser' 无法分配给类型 'RedisJSONObject'。
类型 'myUser' 中缺少类型 'string' 的索引签名。
redis.json.set()
方法期望第三个参数与 RedisJSON
兼容,RedisJSON
的定义如下:
type RedisJSON = null | boolean | number | string | Date | RedisJSONArray | RedisJSONObject;
interface RedisJSONObject {
[key: string]: RedisJSON;
[key: number]: RedisJSON;
}
这个 [key: string]: RedisJSON;
是一个索引签名声明。
当将 MyUser
定义为接口时,它与 RedisJSONObject
不兼容,因为接口不包含索引声明,除非您显式定义它。
在 TypeScript 中,已知类型和接口是“可互换的”。然而,它们的行为有微妙的差异。
除了主要差异之外,类型在不显式定义的情况下包含索引签名,而接口不包含。
这就是为什么在这种情况下,将 MyUser
重新定义为类型可以解决错误的原因。
希望这有所帮助!
英文:
TL;DR
RedisJSON type declaration expects the json object you provide to have an index signature declaration. Your myUser
interface doesn't have it, therefore they are incompatible.
You need to either use a type (more on that below) instead of an interface, or explicitly include the index signature in your interface declaration.
The following code works:
type UserLogins = {
token: string;
active: boolean;
}
type MyUser = {
name: string;
id: string;
logins: UserLogins[];
}
async function redisQuestion() {
const redis = createClient();
const objToStore: MyUser = {
name: 'Karl Mustermann',
id: '1',
logins: [],
};
await redis.json.set('key', '$', objToStore);
// You can use type assertion here to tell Typescript which type will the GET return.
// You should include the 'null' to force you to check for a null result and prevent
// runtime errors.
const redisUser = await redis.json.get('key') as MyUser | null;
console.log(redisUser);
}
Explanation
The code you provide throws the following Typescript error:
> Type 'myUser' is not assignable to type 'RedisJSONObject'.
> Index signature for type 'string' is missing in type 'myUser'
The method redis.json.set()
expects the third parameter to be type-compatible with RedisJSON
, which is defined like so:
type RedisJSON = null | boolean | number | string | Date | RedisJSONArray | RedisJSONObject;
interface RedisJSONObject {
[key: string]: RedisJSON;
[key: number]: RedisJSON;
}
This [key: string]: RedisJSON;
is an index signature declaration.
When defining MyUser
as an interface, you make it incompatible with RedisJSONObject
because interfaces don't include an index declaration unless you explicitly define it.
It is known that, in Typescript, types and interfaces are "interchangeable". However, there are subtle differences in how they behave.
Apart from the key differences, types include an index signature without explicitly defining it, whereas interfaces don't.
That's why, in this case, redefining MyUser
as a type solves the error.
I hope that helps!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论