Skip to content

Proposal: string literal type manipulation in mapped types #22041

Closed
@ericanderson

Description

@ericanderson

I would like the ability to do string manipulation within my types. Examples could include stripping out properties that match a regex/prefix/suffix or mapping types to include additional properties derived from the keys of existing ones.

Some examples might explain best:

Example

declare loadThings<T>(T): PossiblyLoading<T>;
declare getTheBar(id: number): Loader<Bar>;

let foo: { bar: Bar | undefined, barLoading: boolean };

foo = loadThings({
  bar: getTheBar(55302),
});

Where PossiblyLoading might be implemented like so:

type PossiblyLoading<T> = {
  [K in keyof T]: UnwrapLoader<T[K]>;
  [(K in keyof T) + "Loading"] + ?: boolean
}

Both should work because the string literal is easily detectable vs the token ?.

This should also work with generic types that extend string:

type MutateProps<T, P extends string, S extends string> = {
  [P + (K in keyof T) + S] + ?: T[K]
}

But I would also want to be able to use these within conditional types, using standard javascript functions:

type RemovePrefixed<T, P extends string> = {
  [K in keyof T]: K.startsWith(P) ? never : T[K];
}

And we could even remove a prefix:

type RemovePrefix<T, P extends string> = {
  [(K in keyof T).startsWith(P) ? K.slice(P.length) : K]: T[K];
}

If we wanted to avoid getting too crazy with function calls we could perhaps do it like this:

type RemovePrefixed<T, P extends string> = {
  [(P + infer K) in keyof T ? never : K]: T[K];
}

type RemovePrefix<T, P extends string> = {
  [(P + infer K) in keyof T ? K : never]: T[P + K];
}

Although I think the one that supports a subset of string function is more broadly useful. For example, we could probably do something around indexing into "foo.bar.baz" and resolve the innermost type of baz.

cc/ @ahejlsberg @mhegazy

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions