Skip to the solution
HardDSA6 min read

How would you use Symbol.hasInstance and Symbol.toPrimitive to customize instanceof checks and type coercion for a class?

172 views

The problem

Question presented to candidate: "Two separate customization hooks: Symbol.hasInstance lets a class define its own instanceof logic instead of the default prototype-chain walk, and Symbol.toPrimitive lets a class control exactly how it coerces to a number, string, or generic primitive value. Implement both on a couple of small example classes, and explain: what are the three coercion hints, and which JavaScript operators actually use each one?"

What a strong answer should cover:

  • Symbol.hasInstance is a static method that, when defined, COMPLETELY REPLACES what instanceof does for that class β€” it does not run in addition to the prototype-chain check, it overrides it entirely.
  • Symbol.toPrimitive is an instance method taking a single hint argument, which is always one of exactly three string values: "number", "string", or "default".
  • Without a Symbol.toPrimitive, coercion falls back to the older two-method protocol: valueOf() is tried first for hint "number"/"default", toString() is tried first for hint "string".
  • The specific hint-to-operator mapping is easy to get wrong from memory: Number(x) and unary +x use "number"; String(x) and template literals use "string"; and β€” the narrowest bucket, not the widest β€” ONLY binary + and loose equality (==/!=) use "default". Every other arithmetic operator (-, *, /, %, **) and every relational operator (<, >, <=, >=) uses "number" directly, not "default".
  • A Symbol.toPrimitive implementation must return an actual primitive value; returning an object throws a real TypeError.

Clarifying questions expected:

  • "Should Symbol.hasInstance validate the value's type strictly, or is duck-typing acceptable?" β€” a real design question, since a permissive check can make instanceof misleadingly pass for unrelated values.
  • "Does the class need value equality (two instances with the same underlying value being ==) in addition to coercion, or is coercion to a primitive enough on its own?" β€” clarifies whether Symbol.toPrimitive alone covers the requirement, since == on two objects still compares by reference unless both sides coerce to the same primitive.

Code / implementation expected: Yes β€” two small classes plus a runnable test that logs which hint is actually passed for each real operator, since that mapping is exactly the kind of claim that must be verified, not recalled.

  • symbol
  • well-known-symbols
  • coercion

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

6 min read Β· 8 sections

Run the code

Edit the code and run it here. Each console line with an expected value becomes a test.

JavaScriptSymbol.hasInstance replacing instanceof, and Symbol.toPrimitive's real hint dispatch across every common operator (run directly)

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 162 of 165 in JavaScript

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextHard

What problem do WeakRef and FinalizationRegistry solve, and why should they be used carefully?

Continue