The attribute 'sandwiches' cannot be found within the data type 'string'

In my app, I require an object that can store strings or an array of strings with a string key. This object will serve as a dynamic configuration and the keys will be defined by the user, so I cannot specify types based on key names. That's why I'm using index signatures to accommodate any type of key. The values will consist of arrays in one part of the app and strings in another.

As I try to implement this, I encounter errors indicating that TypeScript is unable to differentiate between a string and an array of strings:

TS PLAYGROUND

type FiltersStateType = {
  filters: { [key: string]: Array<string> | string }
}

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

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

// do I need to type narrow every time to discern between string and string[]?
if (Array.isArray(example.filters.sandwiches)) {
  example.filters.sandwiches.filter(item => item !== 'ham')
}

This issue arises because TypeScript struggles to determine if the value is a string or an array. Do I have to explicitly narrow down the type each time to differentiate between a string and an array of strings?

if (Array.isArray(example.filters.sandwiches)) {
  example.filters.sandwiches.filter(item => item !== 'ham')
}

Answer №1

If you're looking for a solution, I suggest using the following example. The line

[key: string]: Array<string> | string;
is meant for potential properties that may be added in the future. After listing the required properties and their types, it becomes clear that combining multiple types and accessing a property not present in both can pose a challenge. For instance, although the randomString property was not listed, it can still be accessed because both array and string have this common property.

type FiltersStateType = {
  filters: {
    [key: string]: Array<string> | string;
    sandwiches: string[];
    milkshakes: string[];
  }
}

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

example.filters.sandwiches = example.filters.sandwiches.filter(item => item !== 'ham')

console.log(example.filters.sandwiches);
console.log(example.filters.randomString[1]);

Alternatively, you can utilize the as keyword:

type FiltersStateType = {
  filters: {
    [key: string]: Array<string> | string;
  }
}

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

example.filters.sandwiches = (example.filters.sandwiches as string[]).filter(item => item !== 'ham')

console.log(example.filters.sandwiches);
console.log(example.filters.randomString[1]);

Unfortunately, due to limitations in SO Code Snippet, I'm unable to execute the code with as string[].

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to dynamically change the color of text based on its position using CSS, JS, or JQuery?

I am currently working on a corporate website and have been tasked with creating a unique design for a specific page. The design includes the following elements: A body background gradient that transitions from their primary color to white in a top-to-bot ...

Under what circumstances would you need to manually specify the displayName of a React component?

After coming across an article (linked here: https://medium.com/@stevemao/do-not-use-anonymous-functions-to-construct-react-functional-components-c5408ec8f4c7) discussing the drawbacks of creating React components with arrow functions, particularly regardi ...

I am experiencing issues with my buttons not functioning properly after implementing the fetch API in conjunction with express.js

I'm facing a peculiar issue with buttons that are meant to display templates on the client page. This code is executed on the client side. The primary function of this class is to allow the user to click a button, send a request, receive a response c ...

A guide on importing gLTF files into three.js

I've been having some trouble uploading a gLTF file using three.js. Despite fixing some errors, I'm still greeted with a black screen. One solution was adding this to my chrome target directory: ‘path to your chrome installation\chrome.exe ...

Tips for transferring localstorage values from the view to the controller in order to utilize them as a PHP variable in a separate view

How can I pass the value from local storage as a PHP variable when using location.href in the controller after clicking a button? In the view: echo Html::button('Proceed', [ 'onclick' => " var dataVal = localStorage.g ...

Using Twitter bootstrap with Node.js and Express framework

Is it possible to integrate Twitter Bootstrap with Node.js and Express? I understand that I need to place CSS and Javascript files in the ./public directory (if it's set as default). However, when trying to implement Twitter Bootstrap on Node.js and ...

Utilizing Cordova and AngularJS to efficiently retrieve JSON data through XMLHttpRequest in a factory

I've encountered an issue while attempting to retrieve a JSON from an API using XMLHttpRequest within a factory. Despite the debug logs suggesting that everything is functioning correctly, I keep getting an "undefined" response. Below is the code for ...

How can I create a join for my initial column in TypeORM?

I am trying to figure out how to create a verification email for my users, but I'm having trouble understanding how to connect the UserToken table with the user's id in TypeORM. Can someone provide some guidance on this? @Entity({name: "use ...

Tips for linking two tus servers

Trying to find a solution for uploading files with resume capability to Cloudflare using the tus enabled API. The challenge is ensuring that credentials remain secure, which prevents direct uploading from the browser to Cloudflare. This requires implementi ...

Conceal or reveal form elements based on input selection

In my current HTML form generated by PHP, I have multiple instances of the following structure: function show(elem, show){ var elements = elem.parentNode.parentNode.parentNode.getElementsByClassName("hidden"); var i; for(i=0; i<eleme ...

Sending a JSON object with scheduled task cron job

I have a PHP cron job that is quite complex. It retrieves data from an external webpage and consolidates all the information into one variable, encoding it in JSON. Unfortunately, this entire process is slow and consumes a significant amount of time. My d ...

Tips for altering a key within a tree-view:

I am working with a potentially infinite tree-view array: type Tree = { id: number; name: string; email: string; children: Tree[]; }; const tree: Tree[] = [ { id: 1, name: 'Truck', email: '@mail', children ...

Position the typography component to the right side

Is there a way to align two typography components on the same line, with one aligned to the left and the other to the right? I'm currently using this code but the components are aligned next to each other on the left side. const customStyles = makeSt ...

How to Retrieve URL Parameters in Gatsby

As I delve into learning React and Gatsby, I encountered an issue with my page containing URL parameters. Despite everything working smoothly on my local machine, after the gatsby build process, the variable url = undefined. How can I retrieve these para ...

react-data-table-component establishes the structure of the expanded element

Has anyone encountered an issue with the react-data-table-component? I need to pass a row type (typescript model) to the Detail component that is rendered when the row is expanded. Detail: export const Detail = (row: certificates) => { //it works fine ...

Creating a TypeScript definition file to allow instantiation of a module

I'm encountering an issue with creating a declaration file for an existing module. When using JavaScript, the module is imported using the following syntax: var Library = require('thirdpartylibs'); var libInstance = new Library(); I have ...

When I attempt to run JavaScript code on the server, it fails to execute properly

When I run my code on my PC without putting it on the server, it works perfectly fine. However, when I upload it to the server and try to call it, I encounter the following error: Uncaught ReferenceError: crearLienzo is not defined at onload ((index): ...

How to customize the button color in a Next.js application

Help Needed: Issue with Changing Default Button Color in Next.JS Web Application. The button text color appears as grey on Desktop Google Chrome, but shows up as blue on Mobile Chrome browser. I want to unify the color to be grey on both platforms. Custo ...

Making a XMLHttpRequest/ajax request to set the Content-Type header

In my attempts, I have tested the following methods individually: Please note: The variable "url" contains an HTTPS URL and "jsonString" contains a valid JSON string. var request = new XMLHttpRequest(); try{ request.open("POST", url); request.set ...

"electron-builder - initially designated for building app for Mac only, but now configured to build for both Mac

This is my first attempt at creating an electronjs app, so I may not have a full grasp on what I'm doing. I've been following the instructions on GitHub and also this guide from Medium. Here's a snippet of my package.json: { (package.jso ...