Skip to content

Instantly share code, notes, and snippets.

@x7c1
Last active May 31, 2018 13:05
Show Gist options
  • Select an option

  • Save x7c1/d7cb8fa9d14c888ede33cba2f9454da3 to your computer and use it in GitHub Desktop.

Select an option

Save x7c1/d7cb8fa9d14c888ede33cba2f9454da3 to your computer and use it in GitHub Desktop.
example of nominal typing by TypeScript
const showHtml = (html: Html) => console.log(`${html}`);
const html = Html("tagged html sample");
showHtml(html); // tagged html sample
const css = Css("tagged css sample");
showHtml(css);
/*
error TS2345: Argument of type 'TaggedString<"css">' is not assignable to parameter of type 'TaggedString<"html">'.
Types of property 'type' are incompatible.
Type '"css"' is not assignable to type '"html"'.
*/
export type Tagged<A extends string> = {
typeTag: A;
};
export type Tagger<A, RAW> = (raw: RAW) => A;
export const TaggerFrom = <RAW>() => <X>(f: (r: RAW) => X) => {
return <A extends string>(typeTag: A): Tagger<Tagged<A> & X, RAW> => {
return (raw: RAW) => Object.assign(f(raw), { typeTag });
};
};
export type StringTagged<A extends string> = Tagged<A> & {
toString: () => string;
};
export type StringTagger<A> = Tagger<A, string>;
export const StringTagger = TaggerFrom<string>()(raw => ({
toString: () => raw,
}));
export type Css = StringTagged<"css">;
export const Css: StringTagger<Css> = StringTagger("css");
export type Html = StringTagged<"html">;
export const Html: StringTagger<Html> = StringTagger("html");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment