-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to check if an unknown
object is a Union object and narrow type?
#16
Comments
Hi @kahnc, sorry for such a long response. Needed to take a break from being active on GitHub. That is a very good question! In fact I was thinking about this API a lot. It boils down to two choices:
Of course, I like 1st option much better, but it is also harder to do. Here are my thoughts on this Option 1: Safe for persistenceid is just a concat of strings const id = ["Str", "Num"].sort().join('-'); // "Num-Str"
const unionValue = {
k = "Str",
a = 1,
p0= "some value", p1=undefined, p2=undefined,
id = "Num-Str" // <-------------
}
MyUnion.is = (val) => val.id === "Num-Str" Which is probably good enough. E.g. Identity of a Union type is defined by the set of cases (choices) it has. But it does seems kinda wasteful to pass the whole "Num-Str" string around for each value. I would love to use some hashing function, ideally that maps to just an int, because there is very low chance for hash collision within a single application. const idStr = ["Str", "Num"].sort().join('-'); // "Num-Str"
const id = someIntHash(idStr); // 455138 Small int (<2**31) is stored by value in most JS engines vs floats and big integers are allocated on the heap. Thus int would be way more efficient. The only problem that I haven't done my research how to hash a string into an int. Option 2: valid only within an execution contextconst generateId = (()=>{
let id = 1;
return () => id++
}) ()
const unionValue = {
k = "Str",
a = 1,
p0= "some value", p1=undefined, p2=undefined,
id =1 // <------------- assigned at Union type creation
} This solution is super easy to make but very brittle. I use web workers a lot and inability to be able pass union values safely seems off to me. Option 3: work aroundYou can unblock yourself by doing a simple workaround const errStrId = "super unique string that identifies this error"
type WrappedError = {
type: errStrId
val = MyUnion
}
try {
foobar();
}
catch (err: unknown) {
if ((err as WrappedError).type === errStrId) {
// do something with err.val
}
} Please let me know what do you thing about Option 1 and Option 2 Thanks. |
Hey @twop, thanks for the eventual reply! I eventually did just find another way to unblock myself, but I'd like an elegant solution to this. I'm tending towards Option 1, for persistence etc. I'd want to make sure that the chance of a collision is sufficiently low that I can feel confident in a program's correctness. I haven't done any research on hashing strings either so I don't really know enough to say whether hashing would be a good strategy here. |
[ ] bug report
[ ] feature request
[ ] question about the decisions made in the repository
[x] question about how to use this project
If I have some arbitrary union like:
And I have a function that maybe throws a
MyUnion
:How can I tell if the returned value is a
MyUnion
? There doesn't seem to be any function in the API likeMyUnion.is(maybeAUnion)
that could narrow the type.The text was updated successfully, but these errors were encountered: