javascript - Unngå implisitt 'any'-type når du bruker Object.keys i Typescript


Jeg har et objekt med nøkler som jeg har typet, og jeg vil iterere over det og bevare typen deres, og unngå «Element har implisitt typen 'any' fordi 'ContactList' ikke har noen indeks-signatur».

Jeg vet at dette har blitt diskutert mye på Typescripts GitHub-sider, men jeg har ikke funnet noen løsninger for det jeg prøver å gjøre her. Jeg prøver det både med enums og med unions, men jeg får fortsatt feilen.

Eksempel med enums (lekeplass)

enum Names {
  Joe,
  Bill,
  Bob
}

type ContactList = {
  [key in Names]: {
    isFriend: boolean;
  }
}

const contactList: ContactList = {
  [Names.Joe]: {
    isFriend: true,
  },
  [Names.Bill]: {
    isFriend: false,
  },
  [Names.Bob]: {
    isFriend: true,
    },
};

Object.keys(contactList).forEach(name => {
    // turn on 'noImplicitAny' and get error
    console.log(contactList[name])
})

Eksempel med fagforeninger (lekeplass)

type Names = 'joe' | 'bill' | 'bob'

type ContactList = {
  [K in Names]: {
    isFriend: boolean;
  }
}

const contactList: ContactList = {
  joe: {
    isFriend: true,
  },
  bill: {
    isFriend: false,
  },
  bob: {
    isFriend: true,
    },
};

Object.keys(contactList).forEach(name => {
    // turn on 'noImplicitAny' and get error
    console.log(contactList[name])
})

Uansett forteller jeg TypeScript "de eneste nøklene som er tillatt i dette objektet er fra Names" og så vidt jeg forstår indeksignaturer, bør [key in Names] være en av dem, så jeg er ikke sikker på hvorfor jeg ser en feil. Beklager hvis dette er et nybegynnerspørsmål, jeg er fortsatt litt grønn med TS. Takk.

Svar #1

Siden Object.keys kan returnere flere egenskaper enn objektet faktisk inneholder etter type, er returtypen bevisst skrevet som string[]. Ellers ville det vært ganske vanlig at veltypet kode kaster uventede unntak ved kjøretid, som forklart i dette svaret.

Derfor må du få indeks-typen din til å fungere på strenger:

type ContactList = {
  [key: string]: {
    isFriend: boolean;
  },
};

Eller du typekaster og håper på det beste:

contactList[name as Names]

Du kunne også bare:

console.log(...Object.values(contactList));

Relaterte artikler