Typescript-Index-Signatur, die optionale Eigenschaften indiziert
Ich möchte etwas Ähnliches in TypeScript 3.5.3 deklarieren
interface User {firstName: string}
interface Contacts {[index: string]: User | undefined}
Grundsätzlich möchte ich, dass TypeScript mich darauf hinweist, dass die Eigenschaft, auf die ich zugreifen möchte, möglicherweise undefiniert ist. Derzeit ist das nicht der Fall, wenn ich Folgendes schreibe:
const contacts: Contact = {};
const randomId = '1240astat0252';
const user = contacts[randomId]; //typescript doesn't warn me about this being undefined
Bearbeiten: In dem speziellen Projekt, an dem ich gearbeitet habe, habe ich vergessen, strict: true in der tsconfig zu setzen, was keinen Fehler für user.firstName auslösen würde. Im ursprünglichen Zustand der Frage ist die Antwort korrekt.
Antwort #1
Im Allgemeinen warnt TypeScript Sie nur, wenn Sie etwas tun, das potenziell ungültig ist oder höchstwahrscheinlich ein Fehler ist.
In diesem Fall bist du es nicht. Du liest ein Feld, das möglicherweise undefiniert ist, aber das sofort keinen Fehler verursacht, und es ist ein objektähnliches Wörterbuch, was darauf hindeutet, dass das normales Verhalten ist.
Wenn du tatsächlich etwas tust, das definitiv gefährlich ist, wie zum Beispiel verwenden dieser user-Variable und annehmen, dass sie definiert ist, dann bekommst du einen Fehler. Zum Beispiel:
interface User {firstName: string}
interface Contact {[index: string]: User | undefined}
const contacts: Contact = {};
const randomId = '1240astat0252';
const user = contacts[randomId];
console.log(user.firstName); // Error: Object is possibly 'undefined'
Für die meisten Fälle ist das ausreichend. Dies stellt sicher, dass jeder Code, der tatsächlich abgerufene Eigenschaften verwendet, zuerst sicherstellen muss, dass deren Wert definiert ist (z.B. if (user) { ... }).
Wenn Sie einen Fehler bei jedem Zugriff auf unbekannte Eigenschaften erhalten möchten, müssen Sie die Indexsignatur entfernen. Um dann tatsächlich auf Felder ohne Indexsignatur zuzugreifen, müssen Sie TypeScript zeigen, dass das Feld definitiv existiert. Es gibt einige Möglichkeiten, aber als Beispiel könnten Sie einen benutzerdefinierten Typ-Guard verwenden:
interface User {firstName: string}
type HasContact<N extends string> = { [name in N]: User };
function hasContact<N extends string>(x: {}, name: N): x is HasContact<N> {
return name in x;
}
const contacts = {};
const randomId = '1240astat0252';
const user = contacts[randomId]; // Error
if (hasContact(contacts, randomId)) {
const user = contacts[randomId]; // Inside the 'if' this is all good
contacts['differentId']; // Still an error
}
