Exploring the power of a mapped type within a tuple

Can TypeScript ensure the validity of key-value tuples in this function?

function arrayToObject(array, mapper) {
    const result = {};
    for(const item of array) {
        const [key, value] = mapper(item);
        result[key] = value;
    }
    return result;
}

// returns { '1': 2, '2': 4, '3': 6 }
arrayToObject([1,2,3], v => [v, v * 2])

I attempted to enforce tuple validation with TypeScript:

function arrayToObject<TItem, TObject>(
    array: TItem[],
    mapper: (t: TItem) => [P in keyof TObject, TObject[P]]
)

Answer №1

By utilizing TS3.4 and incorporating const assertions, I have devised a robust typing method as follows:

function arrayToObject<A, K extends keyof any, V>
  (array: readonly A[], mapper: (x: A) => readonly [K, V]): { [P in K]: V } {
  const result = {} as { [P in K]: V };
  for (const item of array) {
    const [key, value] = mapper(item);
    result[key] = value;
  }
  return result;
}

const obj1 = arrayToObject([1, 2, 3] as const, v => [v, v * 2] as const)
// const obj1: {1: number, 2: number, 3: number}

const obj2 = arrayToObject(["a", "b", "c"] as const, k => [k, 0] as const);
// const obj2: {a: 0, b: 0, c: 0}

This approach ensures the preservation of literal key values known to the compiler in the mapper's return type. The current limitation lies in the lack of support for higher rank types except for specific enhancements in generic functions.

const obj3 = arrayToObject(["a","b","c"] as const, k => [k, k] as const)

The challenge remains in defining how the compiler can comprehend that {a: "a", b: "b", c: "c"} is the expected type instead of the more generalized

{a: "a"|"b"|"c", b: "a"|"b"|"c", c: "a"|"b"|"c"}
. Nonetheless, I wish you success in your endeavors!

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

Tips for importing several makeStyles in tss-react

When upgrading from MUI4 to MUI5 using tss-react, we encountered a problem with multiple styles imports in some files. const { classes } = GridStyles(); const { classes } = IntakeTableStyles(); const { classes } = CommonThemeStyles(); This resulted in ...

Error when compiling with Component Lab's Autocomplete function for SVG Icons in Material UI

Upon running my project on the browser, I encountered the following error: Error message: ./node_modules/@material-ui/lab/esm/internal/svg-icons/Close.js Attempted import error: 'createSvgIcon' is not exported from '@material-ui/core/utils ...

Angular5+ Error: Unable to retrieve summary for RouterOutlet directive due to illegal state

When attempting to build my Angular App using ng build --prod --aot, I consistently encounter the following error: ERROR in : Illegal state: Could not load the summary for directive RouterOutlet in C:/Path-To-Project/node_modules/@angular/Router/router.d. ...

Compiling Typescript tasks in Visual Studio Code - ensuring output encoding is set correctly

Have you tried manually setting up a typescript compilation task in Visual Studio Code? You can find detailed instructions at this link. When you run the build command (Ctrl+Shift+B), are you seeing an error message from tsc with unknown encoding? Check o ...

Utilizing OverlappingMarkerSpidifier in conjunction with sebm-angular2-google-map

I'm currently integrating OverlappingMarkerSpidifier using SebM Angular 2 Google Maps on angular2 2.0.0. After successfully loading the google maps API with the GoogleMapsAPIWrapper imported from the sebm module, I am running into an issue when execu ...

Error: Issue with accessing the 'get' property of an undefined value (Resolved issue with incompatible imports not functioning)

Encountering an issue while attempting to execute the karma TS spec file. Despite all modules and imports functioning properly without conflicts, the error persists. I've tried incorporating component.ngOninit() into beforeEach() and it(), but to no a ...

TypeScript: The class results in an empty object being returned

I'm encountering an issue with a Typescript Class that I'm attempting to use. Even after instantiating it, I'm not getting the correct class instance. Class GamesService export interface IGame { name: string; online: number; likes: n ...

An issue occurred in NestJs where it was unable to access the property '__guards__' because it was undefined

Currently, I am in the process of incorporating a basic authentication system into my Nest project. After including the following line in my controller: @UseGuards(AuthGuard('local')) I encountered this error message: ERROR [ExceptionHandler] C ...

Creating an interface or type in Typescript with a nested object property that uses keys from the same interface

I am looking to create an interface or type that can restrict the nested object properties based on keys defined in the main interface. class MyClass implements MyInterface { prop1: string; promp2: number; nestedObj: { prop1: string; // Allowed a ...

Having difficulty displaying data in the proper format with two-way binding

In the realm of my webpage, I have a plethora of headings, paragraphs, images, and other data at my disposal. From the backend, a dataset is provided to me that includes an array with various properties housing the desired information. The challenge lies i ...

Acquire keys from a different residence

Currently, I am working on a React component that accepts data through props and I aim to implement safe property access. I have experimented with the following: type Props = { items?: any[]; // uncertain about using type "any" bindValue?: keyof Prop ...

Ways to effectively implement a function type specified in an interface

Consider the following interface: interface MyProps { onEvent: (name: string, data: any) => void; } Is there a way to utilize the function type in order to avoid unused parameter errors during compilation? eventHandler = (name: string, data: any) = ...

Exporting modules in TypeScript using "module.exports"

While working on my Yeoman generator, I initially wrote it in JavaScript like this: "use strict"; var Generator = require("yeoman-generator"); var chalk = rquire("chalk"); module.exports = class extends Generator { initializing() { this.log( c ...

Struggling to retrieve variable within the .catch function in Ionic 3

I am having trouble accessing the toast variable from the constructor in order to toast errors. It keeps showing as undefined, and I'm not sure why. This issue seems to only occur in this class, which is strange. The error message reads "ERROR TypeErr ...

"Facing an issue where ts-node is not recognizing d.ts files, despite tsc being able to compile them

I am currently using typescript along with express and attempting to enhance the request object in express. Below is my server.ts file: import express, { Request, Response } from "express"; const app = express(); app.use(function(req: Request, res: Respo ...

Utilize the global theme feature within React Material-UI to create a cohesive

I'm feeling a bit lost when it comes to setting up React Material-UI theme. Even though I've tried to keep it simple, it's not working out for me as expected. Here is the code snippet I have: start.tsx const theme = createMuiTheme({ ...

Tips for adding a "Select All" feature to a dropdown list?

Currently, I have a dropdown list with a filter for IN and OUT values. The functionality is working as expected: <select class="form-select" style="max-width: 100px" [ngModel]="selectedBrand" (ngModelChange)="onChangeT ...

Using a Typescript typeguard to validate function parameters of type any[]

Is it logical to use this type of typeguard check in a function like the following: Foo(value: any[]) { if (value instanceof Array) { Console.log('having an array') } } Given that the parameter is defined as an array o ...

Using React to Identify the Chosen Option on a Custom Toggle Button

I have successfully implemented a toggle switch using HTML and CSS in my React app. I am now looking for a way to detect the selected option whenever it changes. For instance, if OR is chosen, I would like it to be saved in the selectedOption state, and if ...

Retrieve server information without utilizing data.map since array.map is not a supported function in next.js version 13

Currently, I am developing a list page using next.js 13 to display a collection of projects. I made an attempt to enable server-side rendering for this feature. The implementation is located in app/team/page.tsx import { useRouter } from 'next/navig ...