Skip to content

Allow string manipulation in mapped types #28329

@bschlenk

Description

@bschlenk

Search Terms

  • string conversion
  • camelCase
  • pure string

Suggestion

TypeScript should have the ability to describe pure string translation functions as having a string literal return type as a function of its input, rather than just returning a string type.

This is an example of what I would like to happen:

import { camelCase } from 'lodash';

const foo = 'my-string'; // foo is string literal type 'my-string'
const bar = camelCase(foo); // bar is string literal type myString

TypeScript should be able to infer that bar is actually of literal type 'myString'. This would enable one to more easily describe methods that were programmatically added to a class.

Use Cases

Here is an example in a library I have written:

There is an API which accepts strings in CapitalCase form, and I want to add a function for each one in camelCase form. In order to do this now, I need to create objects for each method that contain both the key expected by the API, and the key that I want to add to the class, in order to augment the class's type.

If TypeScript understood that the camelCase function returned a string literal type, then I wouldn't need to have objects for each key describing both names.

Another use case would be inferring React event handler names from event names.

Let's say I wanted to go from this:

interface Events {
  click: { value: string };
  change: { value: string };
}

to this:

interface ReactEventHandlers {
  onClick: CustomEvent<{value: string}>;
  onChange: CustomEvent<{value: string}>;
}

There is no way to go from Events to ReactEventHandlers with mapped types. But with this feature I would be able to do something like this:

interface MakeEventMap<T> {
  [eventName(K) in keyof T]: CustomEvent<T[K]>;
}

with eventName defined as:

function eventName<T extends string>(str: T): this(str) {
  return `on${camelCase(str)}`;
}

Examples

I would envision something like this:

function camelCase<T extends string>(str: T): this(str) {
   // implementation
}

Of course, for a function to be eligible for this kind of return type, it would have to be a pure function. Otherwise TypeScript wouldn't be able to reliably infer the return value.

Checklist

My suggestion meets these guidelines:

  • [ x ] This wouldn't be a breaking change in existing TypeScript / JavaScript code
  • [ x ] This wouldn't change the runtime behavior of existing JavaScript code
  • [ x ] This could be implemented without emitting different JS based on the types of the expressions
  • [ x ] This isn't a runtime feature (e.g. new expression-level syntax)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions