Is it possible to create a custom string type with calculations in Typescript?

As an illustration:

type EventType = "click" | "dblclick" | "mouseenter"; 
type ListenerPropName = "on" + EventType;

I am attempting to form a ListenerPropName from EventType (like this: "on" + "hover" => "onhover"), but it appears that TypeScript does not allow the addition operator between types. What is the workaround for this issue?

Answer №1

There's no one way to do it, but there are alternative approaches. I personally prefer using tuple types in situations like this. Take a look:

type EventName = "abort" | "afterprint" | "animationend"; //html event names.
type EventListenerPropertyName = ["on" , EventName];

// example value
const x: EventListenerPropertyName = ['on', 'abort']

What you're essentially doing is combining two types similar to string concatenation. We can take this further by introducing generic types and constructing values. Check this out:

type EventName = "abort" | "afterprint" | "animationend"; //html event names.
type EventListenerPropertyName<T extends EventName>  = ["on", T];

// value constructor
const makeEventListenerPropertyName = <T extends EventName>(a: T): EventListenerPropertyName<T> => ["on", a];
// parser to string
const eventListenerPropertyNameStr = <T extends EventListenerPropertyName<any>>(a: T): string => a[0] + a[1];

const x = makeEventListenerPropertyName('abort'); // x is ['on', 'abort']
const y = eventListenerPropertyNameStr(x); // y is onabort

Answer №2

With the new update in Typescript 4.1, you can now utilize template literal string types. An example would be:

type EventName = "abort" | "afterprint" | "animationend"; //html event names.
type EventListenerPropertyName = `on${EventName}`;

To capitalize the first letter of each event, like transforming to onAbort, you can leverage the use of Capitalize from the built-in template literal types.

type EventListenerPropertyName = `on${Capitalize<EventName>}`;

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

Creating a visually appealing stacked bar chart using Chart.js in Angular 9 with multiple bars

Upon integrating Chart.js into my Angular 9 application, I encountered an issue where the expected chart values were not being displayed. In order to address this problem, I need to structure the barChartData according to the format showcased in this stac ...

TypeScript type that accommodates all object interfaces

I have several functions that all take the same type as input but return different types of interfaces. I'd like to define a type that can encompass all these functions, but when I try to do so with: const f: (arg: number) => Object = func; I enc ...

Is it possible to modify the default behavior of a sensitive region within a button?

I created a calculator application in React and overall, it's working fine, however... I've noticed that when I hold a click longer, it only registers as a click if the mouse was pressed down and released on the button itself. Although I unders ...

After I deploy my Next.js code to Vercel, including Google Analytics added by @next/third-parties, I am encountering an error that does not appear in development mode

Lately, I completed a next.js project and integrated Google Analytics using @next/third-parties/google. During development, everything worked perfectly, but upon deploying it to vercel.com, an error popped up. ` ./app/layout.tsx:3 ...

Implementing custom query filtering in apollo-server-express

Most of the requests and changes processed by my server require authorization. But, there are a few specific resolvers that need to be public such as sign-in, register, and forgot-password. How can I enable these resolvers to be accessed selectively and au ...

Is there a way to customize Material UI theme types and make adjustments to existing types using Typescript?

One way to customize the material ui theme is by extending its type and adding new properties, as shown here: For example, if we want to add an appDrawer property, it can be done like this: declare module '@material-ui/core/styles/createMuiTheme&apos ...

Ways to extract values from a javascript hash map by exclusively incorporating an array

So here's the issue I'm encountering. Let's consider the following scenario: let surfaces: Map<any, any> = new Map([{"83.1" => Object}, {"84.1" => Object}]) let arr1 = ["83.1"] This is the desired o ...

The enum cannot be assigned a type of 'string | null'

Within my ProductGender enum, I have: enum ProductGender { Men, Women, } In my getProducts service: public getProducts( gender: ProductGender, category: ProductCategory ): Observable<IProductInterface[]> { return this.httpPro ...

What steps can I take to resolve a dependency update causing issues in my code?

My program stopped working after updating one of the dependencies and kept throwing the same error. Usually, when I run 'ng serve' in my project everything works fine, but after updating Chartist, I encountered this error: An unhandled exception ...

Patiently waiting for the component variable to be assigned through subscription

I am facing an issue with two calls in my component. The second call depends on the result from the first call. In the first call, I set the value for my component variable "locked". The second call should only be executed when the result is true, meaning ...

User interface designed for objects containing multiple keys of the same data type along with a distinct key

I have a question that relates to this topic: TypeScript: How to create an interface for an object with many keys of the same type and values of the same type?. My goal is to define an interface for an object that can have multiple optional keys, all of t ...

Is Highcharts-angular (Highcharts wrapper for Angular) compatible with Angular 4?

I have attempted to install various versions of highcharts-angular, ranging from 2.0.0 to 2.10.0. However, I consistently encounter the same error when running the application. The error message states: Metadata version mismatch for module C:/dev/Angular- ...

What impact does control flow have on narrowing variable types?

Having reviewed this particular question, my current focus is on understanding how variables can be narrowed down using control flow. An example: type T1 = { a?: { b: string } } const t1: T1 = {} t1.a.b // displays error, possibly undefined t1.a ...

Using Angular's ngFor directive to render 3 buttons in each row

I am attempting to show 3 buttons per div with the class "row". Using *ngFor to loop through the array to display buttons with the correct text. Here is a sample of my data: [{"NODE_ID":21.0,"NODE_DESC":"TERMINAL ASSEMBLY",&q ...

Utilize functional JS code within a TypeScript environment

Attempting to integrate this code into a TypeScript project, it is a modified version of the react-custom-scrollbars. I am struggling with TypeScript in regards to declaring types for style and props. In this particular case, I prefer to bypass type check ...

The concept of callback function overloading using generic types in TypeScript

Is there a way to define a callback type in TypeScript that can accept a variable number of generic type arguments while keeping the number of arguments fixed? For instance: export interface CustomFn { <T1>(value1: T1): boolean <T1,T2>(va ...

What is the best way to retrieve the current complete URL in a Next.js/Typescript component?

I'm working on a component and I need to retrieve the current full URL. Here's a simplified version of what I have: /** * Share dropdown component */ export const ShareDropdown: React.FC<{ className: string }> = ({ className, }) => { ...

Is it possible to utilize the element tags from a different custom directive as the template for a new custom directive?

Recently started using angularjs and working on a web application that incorporates custom directives. I want users to have the ability to choose which directives they see upon logging in. To achieve this, I am storing the selected custom directive tags in ...

Error code -8 occurred while executing the yarn dev command, unable to identify the issue

I'm facing an issue with my development script that is structured like this: "scripts": { "dev": "./test.sh", }, Upon running the 'yarn dev' command, I encounter the following error message: Internal Error: ...

Does the Typescript compiler sometimes skip adding braces?

I am encountering a problem with compiling a specific section of code in my Angular2 project. public reloadRecords() { let step = (this.timeInterval.max - this.timeInterval.min) / this.recordsChartSteps; let data = new Array(this.recordsChartSteps ...