Búsqueda de sitios web

arrays - La propiedad no existe en el tipo/no se puede usar como tipo de índice


Quiero tener un objeto que pueda contener cadenas en su raíz, y un arreglo de cadenas en el objeto arrayValues. Este es un objeto de configuración que se utilizará en una aplicación.

Este objeto y sus claves serán dinámicos (definidos mediante los valores del estado del usuario), por lo que no tengo forma de especificar tipos basados en el nombre específico de la clave.

Estaré añadiendo arreglos a "arrayValues" desde una parte de mi aplicación, y cadenas a "filters" desde otra parte de la aplicación.

Sin embargo, estoy obteniendo errores al acceder a las propiedades del objeto:
TS PLAYGROUND

export type FiltersStateType = {
  filters:
    | {
        arrayValues: { // note: this should only appear once in filters object
          [key: string]: Array<string>
        }
      }
    | { [key: string]: string }
}

const example: FiltersStateType = {
  filters: {
    arrayValues: {
      sandwiches: ['ham', 'cheese'],
      milkshakes: ['choc', 'banana'],
    },
    randomString: 'hello',
  },
}

example.filters.arrayValues.sandwiches.filter((item: string) => item !== 'ham') 
// ❌ Property 'sandwiches' does not exist on type 'string | { [key: string]: string[]; }'.
// ❌ Property 'sandwiches' does not exist on type 'string'

const stringKey = 'milkshakes'
example.filters.arrayValues[stringKey].filter((item: string) => item !== 'choc') 
// ❌ Element implicitly has an 'any' type because expression of type '"milkshakes"' can't be used to index type 'string | { [key: string]: string[]; }'.
// ❌ Property 'milkshakes' does not exist on type 'string | { [key: string]: string[]; }'

example.filters.randomString = 'bye'
// ❌ Property 'randomString' does not exist on type '{ arrays: { [key: string]: string[]; }; } | { [key: string]: string; }'.
// ❌ Property 'randomString' does not exist on type '{ arrays: { [key: string]: string[]; }; }

Esperaba que TypeScript entendiera los tipos encontrados en estos objetos como los he especificado en FiltersStateType.

¿Sabes por qué está pasando esto?

Respuesta #1

Esto está ocurriendo debido al Sindicato resaltado:

export type FiltersStateType = {
  filters:
    | {
        arrayValues: {
          [key: string]: Array<string>
        }
      }
    | { [key: string]: string } // this one
// ---^^^^^^^^^^^^^^^^^^^^^^^^^---
}

Como has especificado { [key: string]: string } en la unión, el siguiente objeto es válido:

const example: FiltersStateType = {
  filters: {
    arrayValues: 'hello',
  },
}

TypeScript no puede imponer la forma del valor de la clave arrayValues, ya que { [key: string]: string } en sí mismo significa que cualquier clave puede tener un valor de tipo string. Idealmente, debes cambiar la estructura de tus definiciones de tipo algo así:

// this is just an example, you should
// restructure as per your requirements 
type FiltersStateType = {
  filters: { [key: string]: string },
  arrayValues: { [key: string]: Array<string> }
}

Respuesta #2

Puedes declarar tu tipo FiltersStateType así:

type FiltersStateType = {
  filters: {
    [key: string]: string | {[key: string]: string[]};
    arrayValues: { // can only appear once in filters object
      [key: string]: string[];
    }
  }
}

const example: FiltersStateType = {
  filters: {
    arrayValues: {
      sandwiches: ['ham', 'cheese'],
      milkshakes: ['choc', 'banana'],
    },
    randomString: 'hello',
  },
}

example.filters.arrayValues.sandwiches = example.filters.arrayValues.sandwiches.filter((item: string) => item !== 'ham');
console.log(example.filters.arrayValues.sandwiches);

const stringKey = 'milkshakes'
example.filters.arrayValues[stringKey] = example.filters.arrayValues[stringKey].filter((item: string) => item !== 'choc');
console.log(example.filters.arrayValues[stringKey]);

example.filters.randomString = 'bye';
console.log(example.filters.randomString);

Artículos relacionados