Passing a variable as a generic type parameter in TypeScript

I created a function that can accept either a string or an array of strings, and it returns an object with keys based on those strings.

Below is an example of the function:

type MyType<T extends string> = { [K in T]: string }
const myFunction = <T extends string>(param: T | T[]): MyType<T> => {
    let result = <MyType<T>>{}
    // some code here...
    return result;
}

Using the above code snippet, I have successfully achieved this:

let values = myFunction(['apple', 'orange']);
values.apple // valid
values.other // invalid

However, when I pass a variable to the function, all string keys become valid:

let fruitArray = ['apple', 'orange'];
let values = myFunction(fruitArray);
values.apple // valid
values.other // valid

Is there a way to address this issue so that I can use a variable while still maintaining the expected behavior?

Answer №1

Creating a variable let items = ['apple', 'banana'] changes the type of items to string[], losing information about the specific strings in the array. To maintain the fixed tuple of string literals 'apple' and 'banana', you must use as const in Typescript. As this is a readonly tuple, your function should accept readonly arrays.

const myFunction = <T extends string>(input: T | readonly T[]): outputType<T> => {
let items = ['apple', 'banana'] as const;
let result = myFunction(items);
result.apple // valid
result.orange // invalid

Check out Typescript Playground

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

Angular 4 Web Application with Node-Red for Sending HTTP GET Requests

I am creating a unique service that utilizes Node-red to send emails only when a GET request is made to 127.0.0.1:1880/hello (node-red port), and an Angular 4 web app (127.0.0.1:3000) for client access. Upon accessing the /hello page from a browser, I rec ...

What is the process for designating the TypeScript server side entry point in a "Nuxt TypeScript" project?

In my experience with a JavaScript-based Nuxt project, the server entry is located in server/index.js. Here is the default code for Express.js: const express = require('express') const consola = require('consola') const { Nuxt, Builder ...

The challenges of type verification in Redux reducer

I'm currently facing two specific challenges with Typescript and the Redux reducer. Reducer: const defaultState = { selectedLocation: { id: 0, name: 'No Location' }, allLocations: [{ id: 0, name: 'No Location' }], sele ...

Generating a composer method in TypeScript (Flow $Composer)

While flow supports $Compose functions, the equivalent mechanism seems to be missing in TypeScript. The closest thing I could find in TypeScript is something like https://github.com/reactjs/redux/blob/master/index.d.ts#L416-L460. Is there a native equivale ...

Creating an array with different types of objects involves specifying the types within the square brackets when

Here is an illustration of a type structure: type TFiltersTypes = 'selectableTags' | 'dropdown'; type TSelectableTabsFilterItem = { id: string; label: string; isSelected: boolean; }; type TFilter = { type: TFiltersType ...

Instructions for excluding readonly properties from a type in typescript

Class getters are readonly properties, so it's logical that the code below would throw a type error. class Car { engine: number; get hp() { return this.engine / 2; } get kw() { return this.engine * 2; } } function ...

Enhancing IntelliSense to recognize exports specified in package.json

I have a package.json file where I define various scripts to be exported using the exports field. "exports": { ".": { "default": "./dist/main.es.js", "require": "./dist/main.cjs.js", ...

What could be causing the error message (No overload matches this call) to pop up when attempting to subscribe to .valueChanges() in order to retrieve data from Firestore?

Currently, I am developing an Angular application that utilizes Firebase Firestore database through the angularfire2 library. However, I am encountering a challenge. I must admit that my background is more in Java than TypeScript, so there might be some g ...

Having trouble getting into my own Hook with Next.js to access the localStorage

My goal is to create a hook that can store User credentials such as authToken. I attempted to save the user data to localStorage by creating a custom hook for this purpose. Unfortunately, when compiling my code, I encountered an error stating that window i ...

The value of type 'number' cannot be assigned to type 'string | undefined'

Having an issue with the src attribute. I am trying to display an image on my website using the id number from an API, but when I attempt to do so, it gives me an error in the terminal saying 'Type 'number' is not assignable to type 'st ...

Adding TypeScript files to an Angular project in a Node server

I'm having trouble importing TS files from my Angular project directories into my Node server. I have explored different configurations for a tsconfig.json file specifically for the Node server, but haven't had any success. To run my Node serve ...

Encountering an error while attempting to set up WebDriverIO with Typescript and Cucumber installation

After completing the project setup, the wdio.conf.ts and tsconfig.json files are saved in a folder named tests. However, the wdio.conf.ts file throws an error on this line: import type { Options } from "@wdio/types"; //located in wdio.conf.t ...

Angular 7: Best practices for handling nested responses with this.http.get

Currently following an instructional guide on Angular 7 and have a question regarding the correct method to retrieve a list of items if they are nested rather than at the top level: List at Top Level (working) [ { id: 123, name: 'Name 123'}, ...

typescript makeStyles() functions from material-ui library

I've been struggling to find the correct type without relying on any. I have a working code that styles the component as expected: import { makeStyles } from '@material-ui/core/styles' const useStyles = makeStyles((theme) => ({ mainC ...

Creating a header row in a CSV file with Angular 4/Typescript

Currently, I have a code snippet that retrieves data and saves it to a CSV file. However, the issue is that it's writing the data in columns rather than in a header row. I attempted toggling the 'showLabels' option between true and false to ...

Error: Attempting to modify a constant value for property 'amount' within object '#<Object>'

After fetching data from an API, I stored an array in a state. Upon trying to update a specific field within an object inside the array using user input, I encountered the error message: 'Uncaught TypeError: Cannot assign to read only property 'a ...

Angular 6 - Accessing grandparent methods in grandchild components

I am in need of running the functions of the grandparent component: import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.cs ...

Ensuring compatibility between prettier and eslint for consistent brace style and indentation

For my new project, I have set up prettier and eslint to automatically convert the indentation and brace styles to the correct format. However, I am facing an issue with the following code block: export default class BaseTextMixin implements BaseTextMixi ...

Blurry text issue observed on certain mobile devices with Next.js components

There continues to be an issue on my NextJS page where some text appears blurry on certain mobile devices, particularly iPhones. This problem is only present on two specific components - both of which are interactive cards that can be flipped to reveal the ...

The module 'file-name.png' and its corresponding type declarations are not found in typescript react

I'm attempting to import a png file into my TypeScript React project using the following syntax: import logo from 'assets/Logo.svg'; However, I am encountering this TS error: Cannot find module 'assets/Logo.svg' or its corresp ...