creditkarma / thrift-typescript

Generate TypeScript from Thrift IDL files
Apache License 2.0
155 stars 32 forks source link

Change exceptions to extend Error. #184

Open markdoliner-doma opened 4 years ago

markdoliner-doma commented 4 years ago

This changes exception classes generated for --target thrift-server so that they extend ErrorThriftLike instead of ThriftLike. There's a corresponding thrift-server change to add the ErrorThriftLike class.

As mentioned in the GitHub issue, this is useful because it causes Thrift exceptions to have stack traces and because some frameworks expect exceptions to derive from Error. The GitHub issue mentions graphql-js. Jest's toThrow() function would also benefit from this. Here's an example:

await expect(thriftClient.someFunction()).rejects.toThrow()

toThrow doesn't identify Thrift exceptions as exceptions because they don't derive from Error and so it will return false in such cases. Part of the blame could fall on Jest, because perhaps toThrow should return true for any rejected promise regardless of the type of object being throw, but I think some of the blame still falls on Thrift.

A downside of extending Error is that there's a naming collision when developers define fields named name, message, stack, etc in their Thrift exceptions (because these are defined by the super class). I think this is an acceptable tradeoff. FYI tsc complains if someone defines a field that differs from the super class. For example, if someone has a Thrift exception with 1: required i32 message (because message must be a string) or 1: optional string message (because message is required).

I tried to avoid the naming collisions by manually adding Error to the exception class's prototype chain. It might avoid the tsc compile errors when there's a naming collision but it doesn't really eliminate the problem of same-named properties being used for two different things. And so I think manually changing the prototype chain is a bad solution.

The code generator could possibly try to detect naming collisions between fields in user-defined exceptions and Error, but it doesn't seem super important to me. One difficulty is that different JavaScript implementations set different properties on Error. It would be hard for the code generator to warn about all of them. But message and name are obvious things to warn about.

I didn't change the code generated for --target apache. Those classes also don't derive from Error. As mentioned in https://github.com/creditkarma/thrift-typescript/issues/178 the Apache thrift generator has exception types inheriting from thrift.TException. I think it would be great for our code generator to do the same when using --target apache, but it seemed like a different enough change that it didn't make sense to do it as part of this commit.

Remaining work:

markdoliner-doma commented 4 years ago

I can clean this up a little (fix tests, update documentation as needed, etc), but wanted to get feedback from Credit Karma folks to make sure I'm heading in the right direction before spending more time on it.