Using generics in Typescript, transform an array of strings into various types and values

Enhanced with coding norms

I have obtained an array of fruit values:

const fruitsArray = ["apple", "banana", "peach"] as const;

Utilizing this array as a foundation, I generated types and values in the following manner:

type FruitsType = (typeof fruitsArray)[number]; // "apple" | "banana" | "peach"
type FruitsTypeMap = { [K in FruitsType]: K }; // {apple: "apple", banana: "banana", peach: "peach"}
const fruitsMap: FruitsTypeMap = fruitsArray.reduce(
    (obj, key) => Object.assign(obj, { [key]: key }),
    {} as FruitsTypeMap
); // {apple: "apple", banana: "banana", peach: "peach"}

All functionalities are operating smoothly.

My query is how to create FruitsType, FruitsTypeMap, and fruitsMap from fruitsArray using generics since I have various other arrays resembling fruitsArray.

Answer №1

To simplify your operation, one strategy is to create a single generic function called stringArrToMap(). This function takes an array of strings as input and returns an object where each input string becomes both a key and a value in the output object. Here's how you could implement it:

function stringArrToMap<K extends string>(arr: readonly K[]) {
    return Object.fromEntries(arr.map(k => [k, k])) as { [P in K]: P }
}

I opted to use Object.fromEntries() for a more straightforward implementation. Since there isn't a foolproof way to ensure type safety for all inputs, I utilized a type assertion to inform the compiler that we can treat the returned object as type {[P in K]: P}.

Let's put it to the test:

const fruitsMap = stringArrToMap(["apple", "banana", "peach"]);
/* const fruitsMap: {
    apple: "apple";
    banana: "banana";
    peach: "peach";
} */
console.log(fruitsMap);
/* {
  "apple": "apple",
  "banana": "banana",
  "peach": "peach"
}  */

const otherMap = stringArrToMap(["a", "b", "c", "x", "y", "z"]);
/* const otherMap: {
    a: "a";
    b: "b";
    c: "c";
    x: "x";
    y: "y";
    z: "z";
} */
console.log(otherMap);
/* {
  "a": "a",
  "b": "b",
  "c": "c",
  "x": "x",
  "y": "y",
  "z": "z"
} */ 

Everything appears to be in order. The types and values align with expectations.

Access Playground link here

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

A guide on converting TypeScript to JavaScript while utilizing top-level await

Exploring the capabilities of top-level await introduced with TypeScript 3.8 in a NodeJS setting. Here's an example of TypeScript code utilizing this feature: import { getDoctorsPage } from "./utils/axios.provider"; const page = await getDo ...

Issues arise when attempting to extract data from a data provider using JSON within the context of the Ionic framework

Hey there! I'm relatively new to the world of Angular and Ionic, and I've embarked on a project to create a pokedex app. My approach involves using a JSON file containing an array of "pocket monsters". However, my current challenge lies in extrac ...

Error message in VsCode plugin stating that property 'X' is not found on type '{}' within a Vue 3 template

Currently, I am in the process of setting up my vue-cli project that utilizes the composition API with <script setup> to fully integrate TypeScript. Each time I try to use variables within template tags, VSCode flags errors. I have already installed ...

Nested arrays in an Angular interface

As a newcomer to Angular with a background in Java, I am accustomed to setting up classes as data structures for my information. However, after doing some research, I have learned that interfaces should be used instead. I am facing an issue understanding ...

Creating a concise TypeScript declaration file for an established JavaScript library

I'm interested in utilizing the neat-csv library, however, I have encountered an issue with it not having a typescript definition file available. Various blogs suggest creating a basic definition file as a starting point: declare var neatCsv: any; M ...

The function is trying to access a property that has not been defined, resulting in

Here is a sample code that illustrates the concept I'm working on. Click here to run this code. An error occurred: "Cannot read property 'myValue' of undefined" class Foo { myValue = 'test123'; boo: Boo; constructor(b ...

Issue with manipulating element styles using jQuery in Angular2

My method of assigning IDs to elements dynamically using *ngFor looks like this: <div *ngFor="let section of questionsBySubCat" class="col-md-12"> <div class="subcat-container"> <h4 class="sub-cat">{{ section?.subcategory }}& ...

Errors related to missing RxJS operators are occurring in the browser, but are not showing up in Visual Studio

Recently, I encountered a peculiar problem with my Angular4 project, which is managed under Angular-CLI and utilizes the RxJS library. Upon updating the RxJS library to version 5.5.2, the project started experiencing issues with Observable operators. The s ...

What is the best way to transform an array containing double sets of brackets into a single set of brackets?

Is there a way to change the format of this list [[" ", " ", " ", " ", " ", " ", " ", " ", " ", " "]] to look like [" ", " ", " &qu ...

Images in the Ionic app are failing to display certain asset files

Currently, I am working on an Ionic 4 app for both Android and iOS platforms. The issue I am facing is that only SVG format images are displaying in the slide menu, even though I have images in both SVG and PNG formats. public appPages = [ { ...

Extract data from an HTTP request and assign it to variables using filter and map in Angular

I need to extract data from an http get request and assign it to 3 separate variables once fetched. Data: [ { reportId: 1, results1: [{ name: "TotalReferralsMade", optionId: 3082, factor: 1, description: null ...

Is there a way to increase the level of detail in the error trace provided by tsc? This error trace is

While attempting to compile a React project using the default tsconfig.json provided by create-react-app, I encountered a baffling error that has me stumped. $ tsc error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that ...

When converting to TypeScript, the error 'express.Router() is not defined' may

Currently, I am in the process of converting my express nodejs project from JavaScript to TypeScript. One of the changes I've made is renaming the file extension and updating 'var' to 'import' for "require()". However, there seems ...

Error: Reference to an undeclared variable cannot be accessed. TypeScript, Cordova, iOS platforms

Can anyone offer some advice on what might be the issue? I'm encountering an error while building my Ionic app on the IOS platform, but everything is running smoothly on Android. ReferenceError: Cannot access uninitialized variable. service.ts:31 O ...

Issue with Moment.js: inability to append hours and minutes to a designated time

I have a starting time and I need to add an ending time to it. For example: start=19:09 end=00:51 // 0 hours and 51 minutes I want to add the 51 minutes to the 19:09 to make it 20:00. I've attempted several different methods as shown below, but none ...

Creating HTML elements dynamically with attributes based on the `as` prop in React using TypeScript

Is there a way to dynamically create HTML elements such as b, a, h4, h3, or any element based on the as={""} prop in my function without using if guards? I have seen a similar question that involves styled components, but I am wondering if it can be done ...

A guide on passing variables to the MUI styled function within ReactJS

Is it possible to pass a variable directly to the styled function in order to conditionally change style properties while using MUI styled function? I want to achieve something like this: borderColor: darkMode ? 'white' : 'black' const ...

A guide on incorporating JavaScript variables within a GraphQL-tag mutation

I'm having trouble consistently using javascript variables inside graphql-tag queries and mutations when setting up an apollo server. Here's a specific issue I've encountered: gql` mutation SetDeviceFirebaseToken { SetDeviceFirebaseTok ...

Tips for managing onChange events in TypeScript

I'm still learning Typescript and I have a question regarding handling the onChange event in a TextField component when using Typescript. Can you provide guidance on how to approach this? I currently have a function called handleChangeDate(e: React. ...

What could be causing ESLint to run on its own configuration file while working with Typescript?

I have files named .eslintignore and eslintrc.js in close proximity. The contents of my ignore file are as follows: .eslintrc.js dist/* node_modules/* out-tsc/* However, when I access the eslintrc.js file, an error is triggered: Parsing error: ESLint was ...