Ways to statically type a function that produces an array from 1 to n

I am working on creating a function that can generate an array of numbers ranging from 0 to n, while ensuring that the returned type matches a known array structure at compile time.

const makeFoo = (n: number) => [...Array(n).keys()];
const foo1 = [0, 1, 2] as const; // readonly [0, 1, 2]
const foo2 = makeFoo(3); // number[]
console.log(foo1); // [0, 1, 2]
console.log(foo2); // [0, 1, 2]

Even though both foo1 and foo2 hold the same values, their types differ.

My question is, how can I define the return type of makeFoo to match the structure of foo1? (readonly [0, 1, ... n] where the value of n is also known statically, e.g.

makeFoo = <T extends number>(n: T) => ...
)

Answer №1

If you implement a helper type that is recursive, you can determine the return type based on a generic argument. Keep in mind that you will have to use a type assertion since the `[...Array(n).keys()]` will always be inferred as `number[]`.

type CreateBar<N extends number, R extends any[] = []> = R["length"] extends N
  ? R
  : CreateBar<N, [...R, R["length"]]>;

function createBar<N extends number>(n: N): CreateBar<N> {
  return [...Array(n).keys()] as CreateBar<N>
}

const bar3 = createBar(3);
//    ^? const bar3: [0, 1, 2]
const bar100 = createBar(100);
//    ^? const bar100: [0, 1, 2, 3, 4, 5, 6, 7, ... , 99]

TypeScript Play Area


Note: This approach is limited to generating arrays with up to 999 items. Any number higher will result in the type resolving to `any`.

const bar1000 = createBar(1000);
//              ~~~~~~~~~~~~~
// Type instantiation is excessively deep and possibly infinite.

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

Setting up Electron to utilize TypeScript's baseUrl can be achieved by following a few simple steps

In TypeScript, there is a compiler option known as baseUrl that allows you to use non-relative paths, like: import Command from "util/Command" as opposed to: import Command from "../../../util/Command" While this works fine during compilation, TypeScri ...

Create an array of arrays within a loop using TypeScript

My application contains an object with dates and corresponding time arrays. The console log output is displayed below: 32: { 1514160000: Array [ 1200, 1500 ], 1514764800: Array [ 1200, 1500 ], 1515369600: Array [ 1200, 1500 ], 1515974400: Array [ 700, 12 ...

Problem with execution of TypeScript function from HTML

I have been facing an issue where I am attempting to click a button on an HTML page to trigger a TypeScript function called `getToken()`. Strangely, the function does not seem to get executed when the button is clicked. Surprisingly, I have tested the `get ...

Ways to determine if a specified character sequence is present in an Enumerator?

One of my coding dilemmas involves an enum that looks like this: export enum someEnum { None = <any>'', value1 = <any>'value1', value2 = <any>'value2', value3 = <any>'value3' ...

Unable to bind to property as it is not recognized as a valid attribute of the selector component

I have a situation where I need to pass a variable from one component to another using @input. Here is my parent component : @Component({ selector: 'aze', templateUrl: './aze.component.html', styleUrls: [('./aze.compo ...

invoke a method from a different class within the same component file

I am facing a situation where I have 2 classes within the same component.ts file. One class is responsible for embedding the Doc blot, while the other class serves as the main component class. I need to call a function that resides in the component class f ...

Incorporating node packages into your typescript projects

I have been exploring various discussions on this forum but I am still unable to make it work. My goal is to compile the following code in TypeScript. The code is sourced from a single JavaScript file, however, due to issues with module inclusion, I am foc ...

Tips for ensuring a function in Angular is only executed after the final keystroke

I'm faced with the following input: <input type="text" placeholder="Search for new results" (input)="constructNewGrid($event)" (keydown.backslash)="constructNewGrid($event)"> and this function: construct ...

Angular typed controls allowing for a seamless user experience without the need to

Currently, I am in the process of updating some older forms to include stronger typing in order to address eslint errors. One recurring issue I have encountered is when using the .value operator on abstract controls, it causes an error in my IDE stating "U ...

Steps for enabling a function to return an undefined type

After extensive review, I have discovered that TypeScript has numerous hidden nuances, which make it less strict and accurate. I prefer to utilize 'undefined' as the return type for functions because it accurately reflects the reality of the sit ...

Efficiently transferring input to a Typescript file

Is there a better way to capture user input in Angular and pass it to TypeScript? <form > <input #input type="text" [(ngModel)]="inputColor" (input)="sendInput(input.value)" /> </form> The current method involves creating a ...

Creating a user-friendly interface for an array of objects, complete with an included array containing those same objects

I have an array that I want to iterate through. It contains a single object and an array of objects. How can I create an interface for this structure? What is the appropriate declaration to replace any[]? Here is the code: export const initialPhotoProps: ...

How to start Angular2 prototype with an object literal

export abstract class GridColumn { public field?: string; public sortField?: string; public header?: string; public footer?: string; public sortable?: any = true; public editable?: boolean = false; public filter?: boolean = true ...

Ensuring the accuracy of forms using third-party verification services

While working on an Angular form validation using an external service, I encountered a cannot read property of undefined error. The component contains a simple form setup: this.myForm = this.fb.group({ username: ['', [this.validator.username] ...

Invoke the built-in matcher within a Playwright custom matcher

I am in the process of implementing a custom matcher for Playwright based on the information provided in the official documentation on extending expect. In a similar vein to this unanswered discussion, my goal is to invoke an existing matcher after modifyi ...

How to assign a value to an array within a form in Angular 8

I'm facing an issue with my Angular 8 edit form that utilizes a form array. When I navigate to the page, the form array is not populated with values as expected. Can anyone help me identify and solve this problem? ngOnInit(): void { // Fetc ...

Creating an Ionic 3 canvas using a provider

I recently followed a tutorial on integrating the canvas API into Ionic, which can be found at this link. However, I encountered an issue where all the canvas-related functions had to be placed within the pages class, making it quite cumbersome as these f ...

Discovering the process of iterating through values from multiple arrays of objects and applying them to a new response in Angular 8

Received the following data from an API response: const apiResponse = { "factoryId": "A_0421", "loss": [ { "lossType": "Planned Stoppage Time", "duration": ...

Using TypeScript: creating functions without defining an interface

Can function props be used without an interface? I have a function with the following properties: from - HTML Element to - HTML Element coords - Array [2, 2] export const adjustElements = ({ from, to, coords }) => { let to_rect = to.getBoundingC ...

What are the ways in which I can utilize the private or public keyword in TypeScript?

Having issues specifying private or public properties in my TypeScript files (tsx/ts files) for a React project. The IDE being used is WebStorm 2021.3. TypeScript version in use is 4.5.4. Attempts were made to adjust some properties in the tsconfig.json ...