Achieving this is entirely feasible. Starting from TypesScript 4.1, you have the capability to utilize a Conditional Type alongside a Template Literal Type as demonstrated below:
type EventNames = "DragStart" | "Drag" | "DragStop";
type Prefix<K> = K extends string ? `on${K}` : K;
// --> "onDragStart" | "onDrag" | "onDragStop"
const myEvent: Prefix<EventNames> = "onDrag";
Alternatively, you can explicitly specify that the generic should extend string
to input a prefix:
type EventNames = "DragStart" | "Drag" | "DragStop";
type Prefix<Prefix extends string, T extends string> = `${Prefix}${T}`;
const myEvent: Prefix<"on", EventNames> = "onDrag";