#31

feat: support instanceof on diagnostic handles

Openantfubotwants to merge intofrom

Lets callers check a caught error against one code with error instanceof diagnostics.CODE. Today the handles are arrow functions without a prototype, so that check throws a TypeError. The only alternative is error instanceof Diagnostic && error.code === '...', which repeats the code as an untyped string and only narrows to Diagnostic.

Each handle from defineDiagnostics and defineProdDiagnostics now matches any Diagnostic with its code. It matches by code, not by handle identity, so it also works with the prod Proxy, which builds a new handle on every access. DiagnosticHandle declares Symbol.hasInstance as a type guard, so TypeScript narrows to that code's Diagnostic<Data>, including in the dev/prod ternary.

Docs (Quick start, API reference) and the bundled nostics / add-diagnostic skills now show this as the way to check one code.

This PR was created with the help of an agent.

Activity

13
vercel[bot]16d ago

@antfubot is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

vercel[bot]reviewed16d ago
antfu16d ago

think this would be nice to have

antfuapproved changes16d ago
antfu16d ago

reviewed

posva15d ago

I will give it a proper look. On the surface it’s weird to do an instanceof with something that cannot be new’ed. So my first thought is we can do better

posva14d ago

What do you think of having something like diagnostics.is(err, code)? code being optional and a typed string. It does disable declaring an error code is but I think that's okay.

Here is what I mean: https://github.com/vercel-labs/nostics/pull/33

antfu8d ago

the reason I made it this way was because of:

https://github.com/vercel-labs/skills/pull/2561/changes#diff-8626847e13bfbfddb683ed86873a81e97c0c46de6ee50f4dcdc78924ee133c65L700 https://github.com/vercel-labs/skills/pull/2561/changes#diff-8626847e13bfbfddb683ed86873a81e97c0c46de6ee50f4dcdc78924ee133c65R2701-R2709

while comparing to strings is fine, I feel it should make it hard to have hard references (on renaming/refactoring, for example).

regards the cases in the reference, do you see a better API design that can capture this?

posva8d ago

It does skip some refactoring, but I think it's fine nowadays because of the type safety:

https://github.com/user-attachments/assets/9695aaab-c4d3-44bc-9b89-194e621b26f0

I still want to give it some thought to se other possibilities but I really think that being able to to instanceof on something that doesn't support new is a big issue. instanceof Diagnostic is possible, checking for a specific error is missing a typesafe version (can be done with is), and we might want to check for all possible codes (so instance of a specific collection of diagnostics) and that's still not possible but maybe we can find a better way.

posva3d ago

@antfu I reworked https://github.com/vercel-labs/nostics/pull/33. I went with what I think is the best alternative that keeps that idea of having symbols and not just strings (so refactoring works well), without having an instanceof on something that doesn't have a prototype.

So you can check if an error is just one of one collection, and then just is on each individual handle of each diagnostic to check for specific ones. In that aspect, it looks a lot like your instanceof.

Let me know what you think and I will merge, release and create a PR in skills repo for the refactor