#best way for error handling
562 messages · Page 1 of 1 (latest)
don't think you can, because
- ts and eslint aren't aware of what can and can't throw, generally it's treated as if anything can throw so it's not warned
- if they could check for that, then they wouldn't know if they should warn or if bubbling up is the intended behavior.
i think best you could do is use docs for that, for example jsdoc@throws
I hoped for a different answer, those were my findings so far
There is a vscode plugin, but im mad ts has no error types until this day
It sounds like you want checked exceptions
TS indeed doesn't have it, C# doesn't have it either, Java has it and most people consider it more annoying than useful.
I think most languages that want exceptions to be more than exceptions, opt for the "error as value" paradigm instead.
(On that note though, I'm not sure if a class constructor should ever throw, that sounds like you want a factory function instead)
Yeah I'll try it
@worldly coral @calm creek @lofty gulch https://marketplace.visualstudio.com/items?itemName=michaelangeloio.does-it-throw-vscode
"Call expression tracing (Aka "Calls to Throws") is now set to one level deep. Hope to make this configurable in the future!"
Not sure it's very good unless it tracks all the way down
but thanks all the same @near hinge
@worldly coral im wondering, is it not possible to write a ts plugin which would do this as well?
I've never heard of a TS plugin, in the sense of something that extends the behaviour of TS.
There are eslint plugins that using type information from TS I believe.
But a throwing function isn't a type, so not sure how that would help.
It would be possible to write it into TypeScript. But the challenge is convincing the TS maintainers to accept it.
what was that website again where you can inspect how typescript computes a type again
i wanna see if itsp ossible as a plugin
No clue
There's no way for you to know what a function can potentially throw.
If you are thinking about analyzing a function's code to see what it throws, and then also look at all the functions it calls to see what they throw, that approach won't work because eventually you will descent down to native functions like JSON.parse, which you can't know if and what they will throw.
i would mark those as protentially throwing as well
and then later provide options
i get what you're reffering to
though
And not just native functions, foreign code (eg coming from a package) as well.
im aware
But I have a question, it would be annoying yes, but would it not be better if you can configure ts to literally handle every throw error
via a warning / error
If you do that then the analysis is basically useless, because practically every function will use a native function, so the only result it gives is just "every function can throw."
that would be the "max" level config, i would add a level below it for only look throws written in code
by the user
Yeah at that point you should just go for the "errors as values" paradigm instead.
what do i do in the case of a class creation cancellation?
I dont want to use a factory either, because then I have a factory and then the static methods on that class
^
Wdym by this, can you show some code why it wouldn't work for you?
imagine an VElement class, that element has its own instance, reprensting as an example a html element, it has tagname, attributes etc, but then there are static methods which allow to add an event onto the entire class, like before Element creation, before attribute change etc
Why would having a factory function not allow you to use static methods?
because then you have to improt 2 things, and if someone ignores the factory and creates it directly it would still throw
unless i do 2 classes, in which case instanceof would be nailed
No, you will write your constructor to never throw
The factory function can just be a static method on the class if you don't want to import two things.
what if they create an element if an used id then?
it would NEED to throw
because that element would be invalid
or an " " tagname
i need to do some kind of validation and throw
If it throws, then it's an unrecoverable error.
yeah, because it is
If it's unrecoverable, then there's no reason to catch it.
You just let it bubble all the way up and deal with it at the application root, by just crashing the program or log it.
The only reason you want to catch an error, is to recover.
and this is the reason why I want to warn people when they use my class via the IDE
we came full circle
I don't think there's anything to warn, JSON.parse doesn't warn you either and you just have to read the documentation.
and that imo is bad design
That's not a specific thing to JS either, in C# things can throw and you just read the documentation.
Well you are essentially fighting against the language.
yep
the thing is, i like ts, i want to improve it further
i want my users to write even safer and better code
i know its more verbose
That's a fundamental language design issue, it's extremely hard to retroactively fix that especially in user land.
i agree with that
Just write proper documentation like JSDoc and call it a day, people hover over your constructor will see it.
i will do that anyways, but I want to try to make this plugin
I am faily certain that this would help the eco system as a whole
i can imagine that some teams would love this
even if its more verbose
I rather write more code then have a crash in prod
You just need typings of those functions. Technically you can probably get something like OOM errors from anywhere, but you'd have to ignore that.
@near hinge What are the scenarios causing construction to fail?
If empty tag name "" is an error, you can make a type that prevents that.
You can't really prevent that on the type level.
conflicting ids (during a file load), reffering to invalid tagnames, are two examples
This is basically what https://github.com/microsoft/TypeScript/issues/13219 asks for. It's in the limbo though.
Are the tagnames just HTML element names?
not nessecarily
What makes a tag name valid or invalid?
custom elements, and then - check ik
So it has to be an HTML element, or a defined custom element?
yeah, and i can use a union type for that
but i also have other cases where i cannot fix it like this
If your users are defining custom elements, than you have a problem knowing those custom elements right?
that is not an issue, since custom elements need to be something-something
OK, so here you can use a union
i know
the other thing is
should i always throw so errors are "uniform" with eachother, or should i mix throw and returns, return error where possible?
Up to you. I would aim for a constistent design that returns errors
I would also make all my errors be/extend my own error class
class SuperPackageError extends Error {}
Then it's easy to identify that an error came from the package.
Throw unrecoverable errors, return recoverable errors.
Yeah but i cannot do that with classes
But if you want to return errors, then you probably want to replace the constructors and static methods with all factories. I think you can return an error from a constructor, but I doubt TS will play well with that.
as an example a conflicting id error can be still recovered from => no app crash
but i need to somehow cancel the class creation
so user has to handle that throw
yeah use a function to handle creation is really a good answer
thats a factory, but then I have the issue regarding static methods and instanceof
static methods can be replaced with functions no?
I don't get the issue with static methods and instanceof
So you want to export the class so that you can do instanceof, but you don't want it to be constructed directly
You can probably prevent direct construction
You can make a private constructor.
what
Do you have to type cast to call a private constructor?
i dont even know that private constructors were a thing
Nope.
So how do you create the class? static method?
Yes, private constructor is accessible by static.
Preview:```ts
class A {
private constructor() {
console.log("hello")
}
static make() {
return new A()
}
}
const a1 = new A() // err
const a2 = A.make()```
And you just do whatever throwing logic in make but instead make it return error.
Now you have fully type safe error handling.
hmm, well, this sounds like what i need, now im only sad that I lose the new X syntax
i quite liked it

X syntax?
class A {
private constructor() {
console.log("hello");
}
static make() {
return new A
}
}
const a = new (A as {} as new () => A)()
this works, but it's not nice, because having to cast to {} in the middle loses all safety.
I thought it might be possible to do new (A as new () => A)() which would let you build internally using the assertion but not let A be constructed otherwise.
Just do A.tryCreate() or something, it makes it even clearer that it can fail.
not bad
VElement.tryCreate()
class _A {
foo = 'foo'
constructor() {
console.log("hello");
return new Error('err') as unknown as _A
}
}
const A = _A as new () => _A | Error
const a = new A()
// ^? - const a: _A | Error
I'm not saying that you should do this, but, yeah it exists.
It's probably going to create problems
Preview:```ts
class _A {
foo = "foo"
constructor() {
console.log("hello")
if (1 > 2) return new Error("err") as unknown as _A
}
}
const A = _A as new () => _A | Error
const a = new A()
// ^?
if (a instanceof A) {
console.l
...```
It kinda breaks instanceof
Sure, sounds good.
@worldly coral @calm creek I found that goddamn site https://astexplorer.net/
An online AST explorer.
Oh yeah I know that one haha
Why are you using AST?
experimenting around, I think I wanna solve this throw issue for everyone
even if i will prob use tryCreate
oh
I want to try to make a system which warns you if anything can throw
testing around right now
By contributing to TypeScript or something external?
a plugin later on
typescript itself stated they dont want it
and i heavily disagree
If you write a plugin, how does a person use that plugin?
in the tsconfig you cna add plugins
ah, that's cool
I guess we can write wrappers for functions that throw that we can't change, and handle errors that way. But there doesn't seem to be an effort to provide that
So yes it feels like we could do with improved tooling
the crazy thing is i dont feel like it should be even that hard, im roughly experimenting right now
and it already knows what try catch throw etc is
i think what i will do is just define (if possible) a new property that it can throw and which errors can throw
and always set that at the parrent
Well you'll need to create a data bank of all built in functions that can throw
And ideally we want to know what a function can throw too.
exactly!
and then having a union type

automatically typed errors in try catch
oh holy moly
imagine this with zod
and other tools
function f() {
throw null;
}
try {
f();
} catch (e) {
console.error(e.toString());
}
```this would throw, that's why it's hard
console.error itself might throw if stderr was closed
This is a type error though?
e is unknown
only with that option on, without it it's any
question is now
which option?
if i somehow get it running like this
would i be able to convert it to a plugin easily
or should i immedietly start via a plugin
don't remember the exact name, something like useUnknownInCatchVariables
I have no clue. I'm starting to work on TypeScript source now, but I am a total beginner
I don't have that checked @lofty gulch
@worldly coral you have contacts there whom you can ask where a beginner can learn more about writing plugins
Preview:ts function f() { throw null } try { f() } catch (e) { console.error(e.toString()) }
it's probably on with strict
here take a look
From allowJs to useDefineForClassFields the TSConfig reference includes information about all of the active compiler flags setting up a TypeScript project.
#compiler-internals-and-api is probably the place.
And yeah, it's under strict.
Ah, so I think most people are on strict
even so, a toString method can throw
even though most don't, same as there isn't a mechanism to check errors, there isn't a mechanism to validate that a method doesn't throw
Accessing a property can throw
hell
wait
what word is ahh
the s word is banned
well then i need to configure some levels to that popo, I wanna protect the code by alot, but not unreasonable (unless ur on max level later on, enjoy then your time in hell)
ctrl+z can restore your chatbox
yeah well this is kinda the problem with that feature in the js ecosystem lol, what level is reasonable
const obj = {
get soup() { throw new Error("No Soup For You") }
}
that will be a discussion later on, for now just showing which functions by yourself can throw is already really big imo
iifes?
I meant this is like any throwing function though? If throw typing was implemented, that function is inferred as throwing, and you then need to make that property as able to throw.
top level? can you elaborate?
immediately invoked function expression
a throw at a top level would make an import throw
Hmm, so a module needs to have a can throw status
yes
lemme take notes
you got an example for this?
(() => {
// code
}) ()
hmm
I guess an IIFE just affects the enclosing scope as if it wasn't there
or even like
if (!(process in globalThis)) {
throw "only on node"
}
unless it's async, perhaps.
@lofty gulch the question is as well, is it okay for me to pollute every parent with "unhandled throw" until a try catch or something comes along 
that's what bubbling is, yeah
function f() { // function f inferred as a throwing function
(() => {
throw ('IIFE throws;)
})()
}
and that's not described in the code itself
example?
all code that exists
if there isn't a try/catch, it wants bubbling behavior (or it forgot that)
gtg, ill be back
yessir
I was thinking about this a while ago, and I figured that exceptions should bubble up, with each parent being inferred as a throwing function.
Ideally there would be some kind of hint that a function is not handling a possible error, like coloring throwing function that aren't handling in the current function/module.
And at the top level i.e. the module level, an unhandled error would be an error, but you could annotate to say "this module can throw", which then allows the program to terminate on throw.
exactly!
i wanted to perhaps add a comment
or just have ts ignore
or ts can throw
You might want to read about Checked errors in Java
They have errors which are typed, and Exceptions which are not. Exceptions basically are going to crash the program. Errors are typed are you are expected to handle them.
The interesting thing about checked errors is A) I think that's the only language that does it and B) people don't like them very much.
ye no im not touching that
i try to type whereever throw is possible
i will add levels to strictness
So, read about it with that in mind, that's what not to do. I think the problem with checked errors is that you have to handle the error immediately, i.e. rethrow if you want. And that's laborious.
The Error / Exception thing isn't bad. For example if the machine runs out of memory, you probably aren't trying to catch that error and retry. You just want to crash.
most of the time
Errors are things you can handle, Exceptions are not.
Yes they use class inheretance to distinguish
trouble is, we don't have control over what various functions throw
Every language except Java got it wrong?
also you dont happen to know about how to write ts plugins, do you?
and how they work?
Nope
sadge
TS doesn't have plugins
it does
"Language Service Plugin" <- whatever that is
`Plugins -
plugins
List of language service plugins to run inside the editor.
Language service plugins are a way to provide additional information to a user based on existing TypeScript files. They can enhance existing messages between TypeScript and an editor, or to provide their own error messages.
For example:
ts-sql-plugin — Adds SQL linting with a template strings SQL builder.
typescript-styled-plugin — Provides CSS linting inside template strings .
typescript-eslint-language-service — Provides eslint error messaging and fix-its inside the compiler’s output.
ts-graphql-plugin — Provides validation and auto-completion inside GraphQL query template strings.`
Feels like that would only apply in the editor, but not during compilation.
Yeah, you can write language service plugins for displaying custom sorts of errors in the editor. That's the "language service".
Any clue on whether you could implement tracking of throwing functions in that way?
Like is it limited in what you can do somehow?
But you can't really extend the language itself, so whatever mechanism you did would probably require there to be no new syntax.
Ah
I'm not 100% sure it's impossible, you might be able to write basically a superset of TS and a language plugin that transpiles that superset to "real" TS under the hood and then maps errors back to the original code.
oh no, im not going that way
i will simply extend the error class
and people iwll import it from my plugin
import Exception from plugin
and then use that
huh
and then in the ts type checker i check if its imported from my package
I dont plan to add new keywords
So this will only show functions from your package that can throw?
yeah, in the beginning
But why don't you just not use throw in your own work?
I just want to do this as a general thing
i think other people would like it as well
for json.parse etc later on
I don't get it all
Despite that basically literally everyone you've talked to here has said it's not a good idea?
i still believe some people would like it
It's a controversial feature in Java and Java has fewer issues than a TS version would have
i get that, but i rather have annoying way of writing my app then have it crash in prod if i have many clients
i doubt most ppl in smaller projects would use it
but if you work with multiple people this can be really usefull
Like a ton of people have said, if you don't mind writing your app differently, don't use exceptions
Improved handling of exceptions in TS in general would be good. But I think that's a much bigger project than you will complete most like (in a sense that it takes serious commitment), and there's the very big issues of convincing the TS maintainers to accept it.
For your app/lib, just don't use exceptions.
It's very common. Rust, Go and Scala (good langauges) all don't use exceptions
they use return values as errors
lemme ask a bit around
#ts-discussion message
oh no im aware of that, but im not skilled enough to make a official proposal
Yeah, I don't think you should
im nowhere near skilled enough to do something like that yet
Can't change how JS works
Does this mean ask people you work with / ask people who use your libs what they prefer? Just clarifying.
ask generally around, I mean for me i dont care if i use class.tryCreate or throw
We can return tuples
but i think its a thing we should have in general
return [new Error('err'), 'foo']
thats an le array
Not if you call it a tuple.
LOL
i know we can return that, deconstruct
A tuple refers to an array of set size and shape
ye ye
so I'm confused why we need multiple return, which is basically just tuples
performance
negligible
Oh, read that as "TS proposal" I see it's TC... but yeah, don't think that's happening either.
ye
but people from the prime community and theos community would actually like more info on what can throw
gimme a moment, lemme find a short
Ehh
Here's Anders, a desginer on both C# and TS talking about the problems with checked exceptions: https://www.artima.com/articles/the-trouble-with-checked-exceptions
As said, there are good reasons to have more info on what can throw. What there is not a great reason for is to implement a lib that throws, then have to make some plugin to provide info IMO. If you want to you can, but it's much easier to use a return value approach in your own code.
The desire for help with existing code that throws is real, but that's a much bigger issue.
anyways, pretty sure most if not all built-in stuff can throw
(
conversions/primitive constructors - toString/valueOf/@@toPrimitive can be customized
methods - old versions or overwrite
properties - overwrite
)
maybe just not arbitrary constructors
also anything that isn't writable
idk how much stuff isn't writable tho tbh
but having stuff like Number(x) be able to throw seems like an obstacle
When does Number(x) throw?
i hate my life
kind of
Number("")
i know that that gives 0
At least it is consistently wrong
heh
when valueOf/@@toPrimitive throw
@worldly coral i think what i would do is just mark a function with info that it can throw (via an info) and bubble up info that it can throw, this way it still gives a subtle visual hint
You've gone too deep in the JS for me haha
also, every function can throw with a stackoverflow, but i think that's solidly in the space where you don't care
yeah
it's basically toString but for other types
Is this meaningfully different than JSDoc comments?
/** @throws NullPointerException */
function foo() {
throw new NullPointerException(); // I heard you like java
}
i should perhaps clarify thah this is tough as a supportive tool, I dont expect people to only rely on it
I mean if we just had the ability to explicitly declare what a function throws, without any effort to cover everything, that would be nice
For example Prisma throws errors. With some type annotations we could have info on those common throws.
exactly, thats the idea for ver 1
on a unique constraint violation for example, really bugs me having to catch and process those errors
and probably towards the endgame the default setting and level 0 of checks
I should probably look into this more.
also if you dont handle a error in a function it would mark that function as possible throw as well, so you can have a centralized handler later on
another thing to consider is that there are some errors you don't want to handle
if you have something that interfaces with something else and that something else fails, you may want to just exit asap
unless you have other external stuff you have to free or close, that wouldn't be cleared on process termination, you wouldn't really need or want to catch in cases like that
and that "something else" could just be the web or the file system
(that's the distinction between exceptions and errors in java)
All Clips are from the live stream of ThePrimeagen
https://twitch.tv/ThePrimeagen
Wanna Become a Backend Dev & Support me at the SAME TIME???
noted it
i will also add something like that to my package
"I want errors as values"? Sounds like they're arguing for returning errors as values not exceptions
Yeah, have fun
Yep, he is very Rusty
Yeah, he's a trendy tech youtuber, of course he's rusty
Seems cool, but you still don't have type info of the errors, right?
True
with my plugin i think i would be able to make a module which has the actual errors
I have nothing more to say 🙂
Primeagen is a content creator, I wouldn't take what they say too seriously.
They especially have a thing for hating on JS/TS, there was this one instance where they didn't know about the difference between readonly vs Readonly<T> in TS and proceeded to laugh at TS, chat had to correct them but they didn't acknowledge it. Which is very baffling because clearly they have lots of experience working with JS/TS, yet this is such an entry level knowledge.
A small update: I have a running ts plugin, which can find throws and emit erros into a terminal on use, I am working right now on marking the parent method that it can throw and then adding a info in the diagnostics
wait a sec, I am murdering the quick info panel
I may be stupid
@worldly coral next step is to detect if a catch is in the way or not
but how do i get that error to the next line 
\n king
may i suggest "throws" for that, as java or jsdoc do
good idea, will do
this is just the barebone mvp
@lofty gulch a question is also how do i show a list of multiple throws
just to make sure we're on the same page, by that do you mean you want to specify what kinds of errors each function can throw?
tsdoc way
yep
_imagine you have an throw handler function and the jsdoc is 10 pages long 
wouldn't you just have a list
well jsdoc hover just shows all the tags indiscriminantly
can you mock test it for me?
i don't think i can dedicate time for that right now, im pretty busy, sorry
(if i accept i will not get any actual work done in the next 2-3 days)
I'd display it as a union if possible
throws string | number | object
with the throws a different color to the type
Although I don't know that you can correct condense down unions with overlap at that level.
no worries
I actually want to make them clickable
but i dont know how i would do that
imagine you click it and jump to the throw
sounds like you could utilize codelens
that would be dope
hmm
actually for that it has to be a vscode plugin, does it not?
yeah
you might have a lot of duplication.
can filter them out later
for now that frankensteinsshite should just run 
Does it display if a function's inner function throws?
and oh god, the code cleanup later on
will later on, yes
although would probably have to be in the vein of "show references" rather than "go to definition" since there could be multiple throws
OK
true, but i also show the type instead of the throw
i think thats smarter
or what should i do 
also, how do you plan on treating TypeErrors and such from language or library stuff?
either jsdoc, or for now not at all
you could have multiple throws with partially overlapping unions though
so the exception vs error route
ahh, it will be always just a subtle hint
you can ignore it if its an exception
or i will later add my custom Exception class
which would disable that check
errr that's not what i mean
btw do you know a plugin expert i can ask a difficult question?
i mean just separation in design, not in code
how i understand it is:
throws are like exceptions, known and shown
stuff like null property access or spread with no iterator are like errors, issues that could happen anywhere and you don't particularly want to handle
ahh, for now i just show user defined errors, I will not cover the entire of js, since its near impossible
I need to figure out how to override the type in a try catch error
Ah, tame.
couldn't you just ignore everything inside the try
no i will do that, the reason why i want to do that is it would be really awesome to have typed catch
dont you agree?
oh you mean the catch variable, i misunderstood
Are you saying catch (error) where error should get strongly typed rather than unknown? I would not suggest it since your plugin is not capable of analyzing native and foreign code that throws.
that would just be unknown
T | unknown is just unknown.
really? if you use a if condition, would it still not give like help?
Nope, it's like 42 | number is just number.
unknown is the top type.
if it's | unknown, then a condition specific to the union wouldn't mean anything since it could be something else
my idea was for ide auto complete if you do a chain of if statements to check for the error type
ye autocomplete not working :C
now im sad sad
unknown is analogous to the universe set 𝑈, for any set 𝐴, 𝐴 ∪ 𝑈 = 𝑈
no i understand that
what i was reffering to that the ide still works with what he knows, but allows for the rest
like known key values in a dynamic dictionary
Technically there's a workaround for the string case, but I don't know what kind of 'autocomplete' you would get from a SpecificError | unknown union anyway.
(∀𝐴⊂𝑈[𝐴 ∪ 𝑈 = 𝑈])
maybe a snippet?
OH, so it recommends a snippet?
but thats a vscode plugin again
You can offer a code action.
well, you're talking about stuff that would go through the ide...
true dat 
hmm
perhaps, i should make the ts plugin really good, but then make a extension based on it and do those advanced tools as well
^
wouldn't that also be via an ide plugin
Code action is a LSP thing, any IDE supports LSP can make use of it.
yeah
i had gpt tell me that
i forgot about that

Completion details
maybe
i can actually do it
even if its an unknown type
it shows as unknown but type helper still work
code action via tsc plugin seems a bit of a roundabout way to do it
is that even possible?
it is
code fixed => refactoring
i can make a recommendation to refactor catch() to a catch with all if statements
that would be so good
@lofty gulch imagine you have a function which can error, you go to the catch, press a button, and boom, you have a list of all possible recorded throws and a catch all final one
through tsc?
yes
only question, do i use if else or switch statement?
@calm creek do you want me to immortilize you in the src code?
no
switch (x) {
case y:
}
```is analogous to```ts
if (x === y) {
}
the === is locked in
Eh, I don't really care either way, it's not that big of an insight either.
You can do the (imo ugly) switch (true).
Maybe in 10 more years JS will finally get pattern matching.
isnt that in stage 2 or 3
stage 1
you would need a switch (true) at the top and it doesn't really provide any real benefit over a if chain with much less readable conditions
ye, lets go with if else
