Skip to content

Instantly share code, notes, and snippets.

View ehatricksmith's full-sized avatar

Ed Hatrick-Smith ehatricksmith

View GitHub Profile
/**
* Nominal typing for any TypeScript interface or class.
*
* If T is an enum type, any type which includes this interface
* will only match other types that are tagged with the same
* enum type.
*
* See <https://stackoverflow.com/a/37074697/253686>
*/
export interface Nominal<T> {
interface User {
id: string;
name?: string;
address?: string;
}
interface Node {
id: string;
x?: number;
y?: number;
type UserId = string & Nominal<UserId>;
type NodeId = string & Nominal<NodeId>;
interface User {
id: UserId;
name?: string;
address?: string;
}
interface Node {
// ❌ Type 'string' is not assignable to type 'UserId'.
const user: User = { id: "abcd" };
function parseUserId(userId: string): UserId {
if (!userId.startsWith("__special__prefix")) {
throw new Error("This is not a userId!");
}
return userId as UserId;
}
// The happy path
const user: User = { id: parseUserId("__special__prefix:abcd") };
type HTMLSafeString = string & Nominal<HTMLSafeString>;
function parseHTMLSafeString(maybeSafeString: string): HTMLSafeString {
return specialHTMLEscaping(maybeSafeString) as HTMLSafeString;
}
function Foo({ userEnteredInput }: { userEnteredInput: HTMLSafeString }) {
return <div dangerouslySetInnerHTML={{ __html: userEnteredInput }} />;
}
npx ts-prune -s '__stories__|\\.stories\\.tsx$'
util/__mocks__/dom.tsx:3 - readMetaOrThrow2
components/ProjectViewPage/board/BoardGroupItem/index.tsx:33 - BOARD_OBJECT_CLASS_NAME (used in module)
components/ProjectViewPage/board/BoardGroupItem/index.tsx:34 - BOARD_OBJECT_ID_ATTRIBUTE_KEY (used in module)
components/ProjectViewPage/insight/TempInsightViewPresentPage/SummaryField.tsx:8 - Props (used in module)
npx ts-prune -s '…patterns here…' | egrep -e '[^)]$'
setTimeout(() => console.log("INTERRUPT"), 10);
// Will these logs be interrupted?
for (let i = 0; i < 1_000_000; i++) {
await (async () => console.log(i))();
}