Type error: Type ‘string’ is not assignable to type ‘number’

When you create an array in TypeScript the type of the first element defines the type of all elements of the array.

When we reuse an array with new data, the array type has already been defined, so when we assign new values to the same array we get the error message:

Type error: Type ‘string’ is not assignable to type ‘number’

If the array only contained one type of data during definition, all elements will be defined as that data type.

let myArray = [1, 2, 3, 4, 5];
// error: Type 'string' is not assignable to type 'number' 
myArray = ['1', '2', '3', '4', '5']; 

If the array definition contained mixed data type, the elements will be defined as “objects”.

let myArray = [1, 'a', 3, 4, 5];
// No error 
myArray = ['b', 6, 'd', 7, 'f']; 

Type ‘null’ is not assignable to type ‘string’

In a TypeScript application ESLint flags code when we try to assign “null” value to string type variables and attributes. This can be necessary when we want to set the value of a database column to “null”.

To make a string type attribute nullable, add ” | null ” to the type definition:

export type Incident = {
  id: number;
  name: string;
  start_date_utc: string | null;
  end_date_utc: string | null;
  description: string;
}

Error: Component definition is missing display name react/display-name

If you use the VirtualTable in a React TypeScript web application ESLint will throw an error when it checks the VirtuosoTableComponents.

Error: Component definition is missing display name react/display-name

The Virtuoso component uses arrow functions to declare the Scroller and TableBody. Arrow functions do not provide the displayName property used by developer tools. We can modify the component to use function definition, which automatically provides the displayName property.

The original example

const VirtuosoTableComponents: TableComponents<Data> = {
  Scroller: React.forwardRef<HTMLDivElement>((props, ref) => (
    <TableContainer component={Paper} {...props} ref={ref} />
  )),
  Table: (props) => (
    <Table {...props} sx={{ borderCollapse: 'separate', tableLayout: 'fixed' }} />
  ),
  TableHead,
  TableRow: ({ item: _item, ...props }) => <TableRow {...props} />,
  TableBody: React.forwardRef<HTMLTableSectionElement>((props, ref) => (
    <TableBody {...props} ref={ref} />
  )),
};

We need to add function definitions and return statements to replace the arrow functions with function definitions.

Replace

(props, ref) =>

with

function myFunctionName (props, ref) {
    return
    ...
}

The corrected code

const VirtuosoTableComponents: TableComponents<Data> = {
  Scroller: React.forwardRef<HTMLDivElement>( function myScroller (props, ref) {
    return (
    <TableContainer component={Paper} {...props} ref={ref} />
  )}),
  Table: (props) => (
    <Table {...props} sx={{ borderCollapse: 'separate', tableLayout: 'fixed' }} />
  ),
  TableHead,
  TableRow: ({ item: _item, ...props }) => <TableRow {...props} />,
  TableBody: React.forwardRef<HTMLTableSectionElement>( function myTableBody (props, ref) {
    return (
    <TableBody {...props} ref={ref} />
  )}),
};

Horizontal scrolling cards

We can use simple CSS settings to scroll cards horizontally in a container.

Apply these settings to the container <div>:

.horizontal-scrolling-container {
  overflow-x: scroll;
  overflow-y: hidden;
  white-space: nowrap;
  -webkit-overflow-scrolling: touch;
}
  • Enable the horizontal scroll bar,
  • Hide the vertical scroll bar,
  • Disable wrapping to force every card in one line.container
  • Enable the bouncing stop at the last card on iOS.

Configure the card <div>s with this:

  .card {
    display: inline-block;
  }
  • Force every card into one horizontal line.

… you might have mixed up default and named imports

In a Next.js React web application we can export functionality two ways:

  • As a function definition
    export function InsertDataTest(props) {
    ...
    }
  • As an arrow function
    const SelectDataTest = () => {
    ...
    };
    export default SelectDataTest;

The two definitions have to be imported with two different syntaxes

  • Use the named import for function definitions
    import { InsertDataTest } from './_insertDataTest';
  • Use the default import for arrow functions
    import SelectDataTest from './_selectDataTest';

If we try to use the wrong import statement, we get the following error message: 

Unhandled Runtime Error
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of `Index`.

Make sure your import statement matches the definition format.

The top-level-await experiment is not enabled

When we try to call an async function with await from a .tsx file in a Next.js React TypeScript web application we get the error message:

Module parse failed: The top-level-await experiment is not enabled (set experiments.topLevelAwait: true to enabled it)
Error: The top-level-await experiment is not enabled (set experiments.topLevelAwait: true to enabled it)

The new versions of Next.js comes with Webpack 5, which supports top level await, but we need to enable it for Next.js too.

  • Open the next.config.js file in the root directory of your Next.js React TypeScript web application
  • Add the following section to it
module.exports = {
  webpack: (config) => {
    config.experiments = { ...config.experiments, topLevelAwait: true };
    return config;
  },
};


Module not found: Can’t resolve ‘fs’

If you use Webpack version 5 or later you may encounter the error message

Module not found: Can’t resolve ‘fs’

The cause is, that Webpack 5 has a breaking change, and the “fs” module is most likely not included anymore in the client-side code.

To eliminate the issue, add the “browser” element to the package.js file under dependencies:

{  
  "dependencies": {
   ...
  },
  "browser": {
    "fs": false,
    "os": false,
    "path": false
  }
}

If the error persists, add the “fs”, “os” and “path” elements to the fallback element in the webpack.config.js file:

module.exports = function (webpackEnv) {
  ...
  return {
   ...
    resolve: {
      ...
      fallback: {
        "fs": false,
        "os": false,
        "path": false,
      }
    }
  }
}

Linking between pages in multi page Next.js React web applications

The Next.js React sample project only contains a single “Index” page. If your web site has multiple pages, you need to set up simple routing to call them from each other.

In this example we will use the “Link” Next.js React component to call two pages from each other with the minimum number of instructions using TypeScript.

Create the pages

File location

For automatic routing we need to place our pages into the “pages” directory. We can use nested folders, but in that case the call has to include the folder name too.

File locationURL
pages/index.tsx/ (index is the default file in every directory)
pages/addresses.tsx/addresses
pages/company/index.tsx/company (index is the default file in every directory)
pages/company/people.tsx/company/people

Requirements

  • Import the “Link” React component. It will automatically generate the URL to the referenced page,
  • “export” the function to make it available for routing,
  • Use the “<Link href=>” element to specify the target page hyperlink,
  • {/* */} is the comment block in React,
  • We use the .tsx file extension in our TypeScript applicaiton.

The code

This is the minimum code you need to call a page within your Next.js React web application.

The “pages/contact.tsx” file

// Import the Link component from next/link
import Link from 'next/link'

// Export the function to make it available to other modules
export default function Contact() {
  return (
    <>
    {/* Text on the page. */}
    This is the Contact page.<br/>
    {/* The link to the other page */}
    <Link href="/about">About</Link>
    </>
  )}

The “pages/about.tsx” file

// Import the Link component from next/link
import Link from 'next/link'

// Export the function to make it available to other modules
export default function About() {
  return (
    <>
    {/* Text on the page. */}
    This is the About page.<br/>
    {/* The link to the other page */}
    <Link href="/contact">Contact</Link>
    </>
  )}