typescript - Osäker tilldelning av ett `any`-värde när det används för att bekräfta objektets egenskap i okänd


Jag försöker skriva lite kod för att hantera fel i ett JSON:API-svar.

const handleResponseErrors = (
  response: unknown,
) => {
  if (response && typeof response === 'object' && 'data' in response) {
    const { data } = response;
    // Ensure we have a data object.
    if (data && typeof data === 'object') {
      // Throw errors returned by Drupal.
      if ('errors' in data && Array.isArray(data.errors) && 0 in data.errors) {
        if (typeof data.errors[0] === 'object' && 'detail' in data.errors[0]) {
          const { detail } = data.errors[0];
          if (typeof detail === 'string') {
            throw new Error(detail);
          }
        }
      }

Jag är förvirrad eftersom @typescript-eslint ger ett fel för raden const { detail }=data.errors[0];:

Osäker tilldelning av ett any-värde.

Så jag provade det här:

if (
  typeof data.errors[0] === 'object' &&
  'detail' in data.errors[0] &&
  typeof data.errors[0].detail === 'string'
) {

Detta ger också ett fel:

Osäker medlemsåtkomst .detail på ett any-värde.

Dokumentationen om no-unsafe-assignment föreslår att man typar objektet. Men i mitt fall försöker jag arbeta med unknown för att vara extra säker så att min körningstidkod inte är beroende av typer för att bearbeta svaret. Jag trodde att genom att använda property in object och typeof object.property === type skulle jag kunna få eslint att förstå att typen inte är any, men detta fungerar inte.

Vad gör jag för fel?

Svar #1

Felet kommer från linter; any-tilldelningen är giltig.

Typescript härleder att hela data.errors är any[] från Array.isArray(data.errors)-kontrollen. Denna härledning ändras inte efter den efterföljande kontrollen som letar efter egenskapen 'detail' i data.errors[0]. Denna härledning är en Typescript-funktion.

För att förhindra de fel som genereras av linter måste du åsidosätta isArray-metodens gränssnitt:

interface ArrayConstructor {
  isArray(arg: any): arg is ReadonlyArray<unknown> | Array<unknown>;
}

Detta kommer att ändra typen av data.errors till readonly unknown[] | unknown[].