The error you already know
You have a function that needs something able to send. In Python you would reach for an ABC, have the class inherit it, and prove membership with isinstance before you trust the value. Ported straight across, the reflex reaches for instanceof, and the compiler stops you at the type name.
interface Notifier {send(message: string): void;}// the isinstance reflex, ported// straight acrossfunction alertOps(n: Notifier) {if (n instanceof Notifier'Notifier' only refers to a type, but is being used as a value here.) {n.send("deploy finished");}}
Notifier is an interface. It describes a shape and then vanishes before the program runs, so there is no class sitting in memory to check against. The deeper surprise is that the check was never the point. You were taught the cost up front, a base class to inherit and a gate to pass through. TypeScript does not charge it.
notify.ts(8,20) 'Notifier' only refers to a type, but is being used as a value here.
Watch the habit become the idiom
The fix is less code. You delete the class and the gate, keep the shape, and let the compiler match by structure the way Python matches by behavior.
Step through it at your own pace. Each click is one move.
Step 1 of 4
Python. A class inherits the ABC to count as a Notifier.
class Notifier(ABC):
@abstractmethod
def send(self, msg): ...
class Slack(Notifier):
def send(self, msg):
post(msg)Here's what each move does.
- Start with the Python habit, an ABC that a class must inherit to count as a
Notifier. - Port it and the class earns nothing. It exists only to wear the name.
- Drop the class. A plain object with a
sendmethod already satisfiesNotifier. - Keep only the shape. Any object that matches gets in.
That last move is the one the ABC never allowed. Inheritance asks what an object was declared to be. A structural type asks what an object can do. Python answered that question at runtime and trusted the answer. TypeScript answers it before the program runs, which is all duck typing ever wanted.
Now make the compiler agree
Sink is a structural type with two members. Build fileSink as a plain object that satisfies it, a name string and a write method. No class, no as cast, just the right shape. When the object matches, the compiler runs out of complaints.