TypeScriptadvanced
Narrowing with in and tagged interfaces for a plugin system
interface LoggerPlugin { kind: "logger"; log(message: string): void }
interface CachePlugin { kind: "cache"; get(key: string): unknown }
export type AppPlugin = LoggerPlugin | CachePlugin;
Narrow a plugin union by checking which method it has, instead of switching on a kind tag, so adding a capability-only plugin needs no tag.