A guide on creating a function that can detect if an object is not iterable and then throw an error

Exploration

Uncomfortable type definition at the library:

declare type Extension = {
    extension: Extension;
} | readonly Extension[];

Type-validation function

export function isIterable(x: any): x is Iterable<unknown> {
  return Symbol.iterator in x;
}

Solution Implementation

Utilizing the type-validation function

const extensions:Extension = getExtensions();
if (!isIterable(extensions)) { // Validation
  throw Error('extensions should be iterable');
}
console.log(...extensions); // Executing successfully

Dilemma

Efforts to devise a Helper function for Type-checking:

import { isIterable } from '../type-guarded/isIterable';

export const throwIfNotIterable = <T,>(value: T) => {
  if (isIterable(value)) {
    return value;
  }

  throw TypeError(
    `Expected to be iterable, but received ${value} (${typeof value})`
  );
};

Note: Inferred type:

const throwIfNotIterable: <T>(value: T, name: string) => T & Iterable<unknown>;

Trial and Error

Attempt 1

console.log(...throwIfNotIterable(extensions));

ERROR:

Type 'unknown' cannot be assigned to type 'Extension'.

Attempt 2

throwIfNotIterable(extensions, 'not iterable');
console.log(...extensions);

ERROR:

Type 'Extension | undefined' should have a '[Symbol.iterator]()' method that provides an iterator.

Seeking insight on my errors?

Answer №1

To transform your throwIfNotIterable function into an assertion function, consider renaming it to assertIsIterable as is common practice for assertion functions:

export function assertIsIterable<T>(
    value: T | Iterable<unknown>
): asserts value is Iterable<unknown> {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    if (!isIterable(value)) {
        throw TypeError(`Expected to be iterable, instead got ${value} (${typeof value})`);
    }
}

// ...

const extensions: Extension = getExtensions();
assertIsIterable(extensions);
console.log(...extensions); // Works

Playground example

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

Assigning a dynamic name to an object in Typescript is a powerful feature

Is there a way to dynamically name my object? I want the "cid" value inside Obj1 to be updated whenever a new value is assigned. I defined it outside Obj1 and then called it inside, but when I hover over "var cid," it says it's declared but never used ...

Jest tests are failing to render React IonDateTime component

While executing Jest on an Ionic React component, I encountered a test failure consistently, regardless of whether the component had a time value or not. test('IonDateTime display', () => { render(<IonDatetime data-testid="foo" ...

What is the method for obtaining the return type based on the type of a generic function?

Within my api function, I utilize a parser function that is generic and typically returns the same type as its input. However, in some cases, this may be different for simplification purposes. When using the api function, I am able to determine the type t ...

Display various react components based on the value of the property

I am in the process of creating an input component in ReactJs with typescript. The input can vary in types such as text, date, select, or textarea. Depending on the type provided, the displayed control will differ. For example, if set to text, <input t ...

tsconfig is overlooking the specified "paths" in my Vue project configuration

Despite seeing this issue multiple times, I am facing a problem with my "paths" object not working as expected. Originally, it was set up like this: "paths": { "@/*": ["src/*"] }, I made updates to it and now it looks like ...

Adding images to your SVG using Bobril is a simple process that can add visual

I have been attempting to insert an image into an SVG using Bobril, but the following code is not functioning as expected: { tag: 'svg', children: { tag: 'image', attrs: { 'xlink:href': &ap ...

typescript error caused by NaN

Apologies for the repetitive question, but I am really struggling to find a solution. I am facing an issue with this calculation. The parameters a to g represent the values of my input from the HTML. I need to use these values to calculate a sum. When I tr ...

Apollo GraphQL Server is unable to provide data to Angular

I've been facing a challenge for quite some time now trying to make my Angular component communicate with an Apollo GraphQL server using a simple Query (PingGQLService). I'm currently utilizing apollo-angular 4.1.0 and @apollo/client 3.0.0, and h ...

Enhance your Angular application with lazy loading and nested children components using named outlets

Let me start by explaining that the example provided below is a simplified version of my routes that are not functioning properly. I am working on an angular project, specifically a nativescript angular project, and I suspect the issue lies within Angular ...

Challenges arise with data updating following a mutation in @tanstack/react-query

As I work on building an e-commerce website using React, I have a specific feature where users can add products to their favorites by clicking a button. Following this action, I aim to update the profile request to display the user's information along ...

Is there a point in bundling NPM packages if they are ultimately going to be bundled by the project

I'm in the process of creating a TypeScript package for publication on NPM. My plan is to utilize this package in upcoming web development endeavors, most likely utilizing Vite. As I look ahead to constructing a future website with this module, I am c ...

Is there a way to navigate directly to the code in a TypeScript type definitions index.d.ts file within Visual Studio Code?

When I command-click on the express() function, it takes me to its definition: const app = express(); In vscode, it leads me to this line in an index.d.ts file: declare function e(): core.Express; However, when I try to jump to the definition of e(), i ...

Unable to retrieve func from PropTypes

Struggling to understand why this specific import, among others, is not functioning properly: import * as React from 'react'; import TextField from '@material-ui/core/TextField'; import * as PropTypes from 'prop-types'; impor ...

Adjusting the audio length in React/Typescript: A simple guide

I'm currently developing a web app with React and TypeScript. One of the components I created is called SoundEffect, which plays an mp3 file based on the type of sound passed as a prop. interface ISoundEffectProps { soundType: string, // durat ...

The script type `(close: any) => Element` cannot be assigned to type `ReactNode`

Encountering a problem while adding a popup in my TypeScript code Error: Type '(close: any) => Element' is not compatible with type 'ReactNode'. <Popup trigger={ <button className="fixed bott ...

TSX implementation of a paginator with an ellipse in the center

Looking to add ellipses in the Pagination, specifically when there are more than 10 pages (e.g., 1 2 3 4 ... 11 12 13 14). I've tried various methods but need guidance as a beginner. Can anyone suggest changes based on my code to help me achieve this? ...

Transform the IO type to an array of Either in functional programming with the fp-ts

Looking for assistance with implementing this in fp-ts. Can someone provide guidance? const $ = cheerio.load('some text'); const tests = $('table tr').get() .map(row => $(row).find('a')) .map(link => link.attr(&apos ...

I am looking to generate an array with key-value pairs from an object that will be seen in the examination

I have a task that involves configuring a table and creating objects with key-value pairs for each key. type KeyValuePair<T> = {/** ... */}; let userKeyValuePair :KeyValuePair<{id:number,userName:string}>; // => {key:'id',value: ...

Error in Angular SSR: Build failed due to project reference without "composite" setting set to true

Currently facing an issue while developing an Angular App with SSR. When using npm run build:ssr, the following errors are displayed: ERROR in [...]/tsconfig.json [tsl] ERROR TS6306: Referenced project '[...]/tsconfig.app.json' must have se ...

What is the best way to delegate the anonymous function logic contained within the subscribe() method?

Imagine you have a code block similar to this: constructor(private _http: HttpClient) { this.fetchUsers(5); } employees: any[] = []; fetchUsers(count: number) { this._http.get(`https://jsonplaceholder.typicode.com/users`).subscribe( ...