node.js - Nodejs + Typescript + RedisJSON
Ich habe gerade angefangen, ein wenig mit Node.js, TypeScript und Redis zu programmieren. Leider stoße ich auf ein Problem mit Redis: Ich definiere ein Interface für Daten, die in Redis gespeichert werden sollen. Sobald ich jedoch den Typ hinter der Variable angebe, beschwert sich Redis. Dasselbe passiert, wenn ich Schlüssel von Redis abrufe: Wie kann ich TypeScript sagen, welchen Typ die Daten haben?
Beispiel :
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);
}
Die Art und Weise, wie es funktioniert, ist, wenn ich sage
await redis.json.set("key", "$", objToStore as any);
Und wenn ich Werte von Redis bekomme:
await redis.json.get("key") as any as myUser;
Aber es muss doch einen besseren Weg geben?! Hoffentlich kannst du helfen :)
Vielen Dank
Antwort #1
Kurz gesagt
Die Typdeklaration von RedisJSON erwartet, dass das von Ihnen bereitgestellte JSON-Objekt eine Indexsignatur-Deklaration hat. Ihre myUser-Schnittstelle hat diese nicht, daher sind sie inkompatibel.
Sie müssen entweder einen Typ (mehr dazu unten) anstelle einer Schnittstelle verwenden oder die Indexsignatur explizit in Ihrer Schnittstellendeklaration einschließen.
Der folgende Code funktioniert:
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);
}
Erklärung
Der von Ihnen bereitgestellte Code wirft den folgenden Typescript-Fehler:
Typ 'myUser' ist dem Typ 'RedisJSONObject' nicht zuweisbar.
Index-Signatur für Typ 'string' fehlt im Typ 'myUser'
Die Methode redis.json.set() erwartet, dass der dritte Parameter mit RedisJSON typkompatibel ist, was wie folgt definiert ist:
type RedisJSON = null | boolean | number | string | Date | RedisJSONArray | RedisJSONObject;
interface RedisJSONObject {
[key: string]: RedisJSON;
[key: number]: RedisJSON;
}
Dies [key: string]: RedisJSON; ist eine Deklaration einer Indexsignatur.
Wenn Sie MyUser als Schnittstelle definieren, machen Sie es mit RedisJSONObject unvereinbar, weil Schnittstellen keine Indexdeklaration enthalten, es sei denn, Sie definieren sie explizit.
Es ist bekannt, dass in TypeScript Typen und Schnittstellen „austauschbar“ sind. Es gibt jedoch subtile Unterschiede in ihrem Verhalten.
Abgesehen von den Hauptunterschieden umfassen die Typen eine Index-Signatur, ohne sie explizit zu definieren, während Interfaces dies nicht tun.
Deshalb löst in diesem Fall die Neudefinition von MyUser als Typ den Fehler.
Ich hoffe, das hilft!
