Template literal types can build event names from property names.

property event Combining `keyof` with a template literal type keeps watched property names tied to the object shape.

Watched Property Names

key
watched.ts
Replay: real traced execution (multi-file project)
type Settings = {
    width: number;
    height: number;
};

type SettingKey = keyof Settings;
type SettingEvent = `${SettingKey}Changed`;

function formatEvent(event: SettingEvent, value: number): string {
    return `${event}=${value}`;
}

const key: SettingKey = "width";
const settings: Settings = { width: 10, height: 6 };
const event: SettingEvent = `${key}Changed`;

console.log(formatEvent(event, settings[key]));
type Settings = {
    width: number;
    height: number;
};

type SettingKey = keyof Settings;
type SettingEvent = `${SettingKey}Changed`;

function formatEvent(event: SettingEvent, value: number): string {
    return `${event}=${value}`;
}

const key: SettingKey = "height";
const settings: Settings = { width: 10, height: 6 };
const event: SettingEvent = `${key}Changed`;

console.log(formatEvent(event, settings[key]));
  1. key ← width, settings ← [object Object], event ← widthChanged

    10    return `${event}=${value}`;11}1213const key→ width: SettingKey = "width";  //@key="height"14const settings→ [object Object]: Settings = { width: 10, height: 6 };15const event→ widthChanged: SettingEvent = `${keywidth}Changed`;1617console.log(formatEvent(eventwidthChanged, settings[key]10));
  2. function formatEvent(event: SettingEvent, value: number): string

    6type SettingKey = keyof Settings;7type SettingEvent = `${SettingKey}Changed`;89function formatEvent(eventwidthChanged: SettingEvent, value10: number): string {10    return `${eventwidthChanged}=${value10}`;11}
  3. console.log(formatEvent(event, settings[key]));

    14const settings: Settings = { width: 10, height: 6 };15const event: SettingEvent = `${key}Changed`;1617console.log(formatEvent(eventwidthChanged, settings[key]10));
    outputwidthChanged=10
  1. key ← height, settings ← [object Object], event ← heightChanged

    10    return `${event}=${value}`;11}1213const key→ height: SettingKey = "height";14const settings→ [object Object]: Settings = { width: 10, height: 6 };15const event→ heightChanged: SettingEvent = `${keyheight}Changed`;1617console.log(formatEvent(eventheightChanged, settings[key]6));
  2. function formatEvent(event: SettingEvent, value: number): string

    6type SettingKey = keyof Settings;7type SettingEvent = `${SettingKey}Changed`;89function formatEvent(eventheightChanged: SettingEvent, value6: number): string {10    return `${eventheightChanged}=${value6}`;11}
  3. console.log(formatEvent(event, settings[key]));

    14const settings: Settings = { width: 10, height: 6 };15const event: SettingEvent = `${key}Changed`;1617console.log(formatEvent(eventheightChanged, settings[key]6));
    outputheightChanged=6