TypeScript-indekssignatur som indekserer valgfrie egenskaper


Jeg vil gjerne erklære noe slikt i typescript 3.5.3

interface User {firstName: string}
interface Contacts {[index: string]: User | undefined}

I utgangspunktet vil jeg at TypeScript skal advare meg om at egenskapen jeg prøver å få tilgang til potensielt kan være udefinert. For øyeblikket er det ikke tilfelle når jeg skriver dette:

const contacts: Contact = {};
const randomId = '1240astat0252';
const user = contacts[randomId]; //typescript doesn't warn me about this being undefined

rediger: i det spesifikke prosjektet jeg jobbet på, glemte jeg å sette strict: true i tsconfig, noe som ikke ville gi en feil for user.firstName. I den opprinnelige tilstanden til spørsmålet er svaret korrekt.

Svar #1

Generelt vil TypeScript bare advare deg når du gjør noe som potensielt er ugyldig eller svært sannsynlig er en feil.

I dette tilfellet er du det ikke. Du leser et felt som kan være udefinert, men det vil ikke umiddelbart forårsake en feil, og det er et ordbok-lignende objekt som antyder at det er normal oppførsel.

Hvis du faktisk gjør noe som definitivt er farlig, for eksempel bruker den user-variabelen og antar at den er definert, vil du få en feil. For eksempel:

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'

For de fleste tilfeller er det nok. Dette sikrer at enhver kode som virkelig bruker hentede egenskaper først må sørge for at verdien deres er definert (f.eks. if (user) { ... }).

Hvis du vil ha en feil på alle ukjente egenskapsaksesser, må du fjerne indeks-signaturen. For å faktisk få tilgang til felter uten indeks-signatur, må du vise TypeScript at feltet definitivt eksisterer. Det finnes noen alternativer, men som et eksempel kan du bruke en tilpasset typevakt:

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
}

Relaterte artikler