Filling a data entry with simultaneous commitments

Sample code:

type Alphabet = 'a' | 'b' | 'c';

const alphabetMap: Record<Alphabet, null> = { 'a': null, 'b': null, 'c': null}

// Select any asynchronous processing function you prefer
function asyncRandomize(): Promise<number> {
    return new Promise(resolve => setTimeout(() => resolve(Math.random()), 1000))
}

const randomizedValues: Promise<Record<Alphabet, number>>> = Promise.all(
    Object.keys(alphabetMap).map((letter: Alphabet) => 
        asyncRandomize()
            .then((value): [Alphabet, number] => [letter, value])
    )
)

Is there a way to convert randomizedValues to have type

Promise<Record<Alphabet, number>>
instead of
Promise<[Alphabet, number][]>
without using any?

Answer №1

To tackle this issue, you might need a function that mimics the behavior of Object.fromEntries(). However, when it comes to TypeScript typings for such a function, it may end up being too general for your specific requirements. You could potentially receive a type like Record<string, number> instead of Record<I, number>. If you are comfortable with using type assertions, you can opt for that approach:

const irandomized  = Promise.all(
   (Object.keys(is) as I[]).map((i: I) =>
      asyncRandomize()
         .then((v): [I, number] => [i, v])
   )
).then(z => Object.fromEntries(z)) as Promise<Record<I, number>>;

Avoiding the usage of any in this scenario is crucial.


If you prefer not to rely on type assertions within your code, one alternative is to create your custom function akin to Object.fromEntries(), but with more specific typings (keeping in mind that some form of type assertion needs to exist inside the function's implementation). Here's a potential function that might align better with your needs:

type Entry = readonly [PropertyKey, any];
type ExtractSupertype<T, U> = T extends any ? [U] extends [T] ? T : never : never;
function fromEntries<E extends readonly Entry[]>(entries: E): {
   [K in E[number][0]]: ExtractSupertype<E[number], readonly [K, any]>[1] // TS 4.0-
   // [K in E[number] as K[0]]: K[1] // TS 4.1+, easier syntax
} {
   const ret: any = {};
   for (let entry of entries) {
      ret[entry[0]] = entry[1];
   }
   return ret;
}

It's worth noting that once TypeScript 4.1 is released and introduces mapped type as clauses, the ExtractSupertype construct will become redundant.

You can encapsulate this functionality in a separate library. The primary aim is for fromEntries() to convert a strongly-typed array or tuple of entries into a strongly-typed object:

const foo = fromEntries([
   ["x", Math.random()], ["y", new Date()], ["z", Math.random() < 0.5]
] as const);
/* const foo: {
    x: number;
    y: Date;
    z: boolean;
} */

This method ensures that you obtain specific properties associated with distinct types, rather than just receiving a generic

Record<string, number | Date | boolean>
.

Armed with this function, you can proceed without resorting to unsafe type assertions:

const iKeys = ["a", "b", "c"] as const;
const irandomized = Promise.all(
   iKeys.map((k) =>
      asyncRandomize()
         .then(v => [k, v] as const)
   )
).then(fromEntries);

The modification made involved replacing is with an array of its keys. Since no operation was being performed on the values, leveraging Object.keys(is) returned a type of string[] instead of

I[]</code. To simplify things, a strongly-typed tuple of keys was utilized directly.</p>
<p>You can now verify that the output of <code>irandomized
matches your expectations:

/* const irandomized: Promise<{
    a: number;
    b: number;
    c: number;
}> */

Furthermore, confirming its runtime behavior is equally important:

irandomized.then(e => console.log(JSON.stringify(e)));
// {"a":0.9961594084980729,"b":0.015675814053288217,"c":0.1783156372032898}

Playground link for the code

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

In the past, my code would run smoothly without any issues, but now I am encountering a runtime error even though the code comp

Recently, I started learning TypeScript and encountered an issue while working with Classes. My code was functioning properly before but now it's displaying a runtime error. ...

When merging multiple prop definitions using Object.assign in defineProps, Vue props can be made optional

I have defined a const called MODAL_OPTION_PROP to set common props for a modal: export const MODAL_OPTION_PROP = { modalOption: { type: Object as PropType<ModalOptionParams>, default: DEFAULT_MODAL_OPTION, }, }; I am trying to use it in ...

What is the alternative method for applying a CSS class in the click event in Angular 7 without relying on ng-Class or ng-Style?

Is there a way to dynamically add or remove CSS classes to HTML elements in Angular7 without relying on Ng-Style and Ng-Class directives? I'd like to achieve this functionality when clicking on the elements. Appreciate any insights you can provide. T ...

Creating a popup trigger in ReactJS to activate when the browser tab is closed

I am currently working on an enrollment form that requires customer information. If a user fills out half of the form and then attempts to close the tab, I want to trigger a popup giving them the option to save and exit or simply exit. While I have a jQue ...

Step-by-step guide on incorporating an external library into Microsoft's Power BI developer tools and exporting it in PBIVIZ format

I'm attempting to create a unique visualization in PowerBI using pykcharts.js, but I'm running into issues importing my pykcharts.js file into the developer tool's console. I've tried including a CDN path like this: /// <reference p ...

NextRouter does not have a property called "refresh"

Here is the provided code snippet: "use client"; import { useRouter } from "next/router"; import { useState } from "react"; export default function CreatePrompt() { const [title, setTitle] = useState(""); const ...

Error: The identifier HTMLVideoElement has not been declared

Encountering an issue while attempting to build my Angular 9 Universal project for SSR: /Users/my-project/dist/server.js:28676 Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__metadata"])("design:type", HTMLVideoElement) ReferenceError: HTMLVideoElem ...

Difficulty Determining Literal Types that Expand a Union of Basic Data Types

Below are the components and function I am working with: interface ILabel<T> { readonly label: string; readonly key: T } interface IProps<T> { readonly labels: Array<ILabel<T>>; readonly defaultValue: T; readonly onChange ...

JavaScript Equivalent of Declaration in TypeScript

In my Next JS application, I encountered a situation where a line of code relies on a variable from a script src in the app.tsx page. Here's how it looks: app.tsx: <script src="https://js.stripe.com/v3/"></script> config.ts: de ...

Angular 5's data display glitch

Whenever I scroll down a page with a large amount of data, there is a delay in rendering the data into HTML which results in a white screen for a few seconds. Is there a solution to fix this issue? Link to issue I am experiencing HTML binding code snippe ...

Modifying Data with MomentJS when Saving to Different Variable

After attempting to assign a moment to a new variable, I noticed that the value changes on its own without any modification from my end. Despite various attempts such as forcing the use of UTC and adjusting timezones, the value continues to change unexpec ...

What is the reason TypeScript does not recognize the type when dealing with promises?

I am encountering an unexpected behavior where there is no error even though there should be one in TypeScript when using promises. I assigned a number value to a string variable, but surprisingly, no error was thrown. Why does this happen? https://codesa ...

Suggestions for enhancing or troubleshooting Typescript ts-node compilation speed?

Recently, I made the switch to TypeScript in my codebase. It consists of approximately 100k lines spread across hundreds of files. Prior to the migration, my launch time was an impressive 2 seconds when using ESLint with --fix --cache. However, after impl ...

IE11 and how it handles Typescript and promises

Currently, I am utilizing Typescript version 2.4.2 along with Webpack for compilation purposes. Despite successful compilation, when running my code on IE11, an error 'Promise' is undefined arises. Below is a glimpse of my tsconfig: { "comp ...

A step-by-step guide on creating a Decorator using the TypeScript compile API

How can I create a custom class in TypeScript with multiple 'class-validator' decorators to ensure the property types are correct? I am considering using `ts.factory.createDecorator`, but I'm unsure how to obtain a `ts.Expression` for it. ...

Verifying currency in mat-input field

I need help implementing validation for inputting prices on a form. For example, if a user types in $20.0000, I want a validation message to appear marking the input as invalid. Would this type of validation require regex, and if so, how would I go about ...

What are the steps to integrate a database into my Next.js application?

While I was experimenting with integrating postgresql into a nextjs project, I encountered an error 405 when trying to create an account. Below is the error message in the browser console: page.tsx:14 POST http://localhost:3000/api/auth/ ...

Why am I getting the "Cannot locate control by name" error in my Angular 9 application?

Currently, I am developing a "Tasks" application using Angular 9 and PHP. I encountered a Error: Cannot find control with name: <control name> issue while attempting to pre-fill the update form with existing data. Here is how the form is structured: ...

Learn the process of importing different types from a `.ts` file into a `.d.ts` file

In my electron project, the structure looks like this: // preload.ts import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron' import { IpcChannels } from '@shared/channelNames' contextBridge.exposeInMainWorld('api&a ...

Utilizing markModified inside a mongoose class that does not inherit from mongoose.Document

In my Typescript code using mongoose ODM, I am implementing a simple queue structure. The challenge arises when directly mutating an array instead of assigning a new value to it because mongoose doesn't automatically recognize the change. To resolve t ...