Template Literal Types
type EmailLocaleIDs =
| "welcome_email"
| "email_heading";
type FooterLocaleIDs =
| "footer_title"
| "footer_sendoff";
type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`;
type AllLocaleIDs =
| "welcome_email_id"
| "email_heading_id"
| "footer_title_id"
| "footer_sendoff_id"
type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`;
type Lang =
| "en"
| "ja"
| "pt";
type LocaleMessageIDs = `${Lang}_${AllLocaleIDs}`;
type LocaleMessageIDs =
| "en_welcome_email_id"
| "en_email_heading_id"
| "en_footer_title_id"
| "en_footer_sendoff_id"
| "ja_welcome_email_id"
| "ja_email_heading_id"
| "ja_footer_title_id"
| "ja_footer_sendoff_id"
| "pt_welcome_email_id"
| "pt_email_heading_id"
| "pt_footer_title_id"
| "pt_footer_sendoff_id"
type PropEventSource<Type> =
{
on(eventName: `${string & keyof Type}Changed`, callback: (newValue: any) => void): void;
};
/// Create a "watched object" with an `on` method
/// so that you can watch for changes to properties.
declare function makeWatchedObject<Type>(obj: Type): Type & PropEventSource<Type>;
const person = makeWatchedObject ({
firstName: "Saoirse",
lastName: "Ronan",
age: 26
});
person.on("firstNameChanged", () => {});
// Prevent easy human error (using the key instead of the event name)
//person.on("firstName", () => {});
//Argument of type '"firstName"' is not assignable to parameter of type '"firstNameChanged" | "lastNameChanged" | "ageChanged"'.
// It's typo-resistant
//person.on("frstNameChanged", () => {});
//Argument of type '"frstNameChanged"' is not assignable to parameter of type '"firstNameChanged" | "lastNameChanged" | "ageChanged"'.
type Greeting = "Hello, world"
type ShoutyGreeting = Uppercase<Greeting>
type ShoutyGreeting = "HELLO, WORLD"
type ASCIICacheKey<Str extends string> = `ID-${Uppercase<Str>}`
type MainID = ASCIICacheKey<"my_app">
type MainID = "ID-MY_APP"