Comments (11)
@fatcerberus My instinct is that there are at least some cases where it’d be useful to distinguish between the different built-in error types, but I don’t think that making them structurally distinct is a requirement or blocker for this proposal. If this proposal gets any traction, I imagine there’ll be a lot of testing on real-world code before anything lands, and that real world testing should make it clearer whether making the built-in errors distinct is actually worth it.
from typescript.
Today, almost all the built-in Error types have structurally-identical definitions.
Outside of custom error subclasses (which users can make structurally distinct themselves if they need to), is there any real use case for distinguishing between, say, TypeError
and ReferenceError
? Unlike, say, C#, the built-in error classes in JS are very general and often fall at awkward boundaries. In other words you probably wouldn't ever write in JS
try {
// do a thing
}
catch (e) {
if (e instanceof TypeError) {
console.log("invalid data was received by some function");
// error handled, recover
} else {
throw e; // not a type error, rethrow
}
}
because you might get a RangeError
instead of a TypeError
due to the exact same cause (bad data passed to function, e.g.). So IMO it doesn't really matter that they're not structurally distinct.
from typescript.
Without a fully-thought out response, the way I've often alikened something like this is to #26277 ("open-ended union types"), where there is some partially-known set of constituents that you want to handle (for some definition of what "handle" is).
from typescript.
Open-ended unions sounds like what people are often shooting for when they try to write stuff like "foo" | "bar" | string
(if not to aid with completions).
from typescript.
@DanielRosenwasser I hadn’t seen that issue, but this proposal would absolutely leverage open-ended union machinery if it were to exist! Obviously, that machinery alone isn’t enough to cover all the functionality here (e.g., for ErrType
inference), but it's very complimentary.
from typescript.
I really like this proposal.
declaration file improvements should come quickly, whenever a TS-based library is recompiled and republished, because a huge amount of this error information will be inferred;
As far as I understood you want to put the inferred types automatically into generated .d.ts
files (like declare function doSomething(): void throws RangeError;
).
This is a new syntax so old typescript compilers will not be able to parse these files.
Not every consumer of .d.ts
files are quick in upgrading, so IMO we should be able to disable this emit.
Our customers are often consuming our .d.ts
files using typescript 3.9.x :-(
We guarantee this compatibility with a CI build step.
As long as we do not use new syntax (like declare function fancyGetter(name: `get${string}`): number;
, new in TS4.1) in an API this is possible.
from typescript.
IIRC from what maintainers have said, backward compatibility for .d.ts
emit is not guaranteed in general; you're expected to have a downleveling step in your toolchain if you need your declaration files to work with older TS versions than the one you're using.
from typescript.
@DanielRosenwasser If this proposal seems promising, what would the next step be here? Is it the type of thing where the TS team would want to see more community input before anything else? Or is the (long) previous discussion in #13219 already a signal of sufficient community demand? Are there specific issues with the proposal that I could maybe help to address? Or is it more a matter of the TS team talking internally first to figure out how/whether this would cohere with other features TS might add (like open-ended unions), how valuable error typing would be, how hard it'd be to implement, etc?
from typescript.
I think we'd have to allocate some time among the team to get a sense of everything you just listed (e.g. difficulty of implementation, feel, future-compatibility against other possible language features, etc.). Part of it is just a timing/availability thing.
from typescript.
Got it; makes total sense.
Whenever you and the team do have time to talk about it, I’m excited to hear what the outcome is :)
from typescript.
What we've discovered trying (multiple times!) to implement non-workarounded completion lists for open-ended unions is that the instant something doesn't have type system effects, it tends to disappear nearly immediately, or cause huge problems.
Example: having two types () => throws A
(call it TA
) and () => throws B
(call it TB
) be mutual subtypes seems fine, but it isn't. It means, for example, that given const x = e ? TA : TB
, x
has to be one of those types, but can't be a union, so it means TA
or TB
would get randomly picked. Once it gets randomly picked, then it's a huge hazard because people will inevitably try to fish out the throws type with something like type GetErr<F> = F extends (() => unknown throws infer E) ? E : never
, so then type K = GetErr<typeof x>
randomly gets you A
or B
and causes different errors to appear or not appear.
Putting in place type system features which never affect assignability is thus very dangerous, because it means that the behavior of your program becomes chaotic, or you're not allowed to use that feature in any way where it's observable, which becomes its own can of worms. Like you might just say "Oh, well, it's just illegal to write throws infer E
, but that doesn't solve the problem, because you can do a trivial indirection:
const Throws<T> = () => unknown throws T;
type TA = Throws<TA>;
type Unthrows<T> = T extends Throws<infer E> ? E : never;
where now you have a situation where you can't do nominal inference of Unthrows<TA>
because it would cause the illegal observation of the throws
type. So now you have to have a separate system to track "type parameters where it's legal to observe them" and "type parameters where it's not legal to observe them" and come up with sensible error behavior anyone someone tries to cross that invisible line. You can keep stacking on more ad-hoc rules to try to ban this, but you'll always either end up at some extremely inconsistent (and defeatable) set of rules, or prevent the feature from being used in the way it was originally intended in the first place.
Ultimately this doesn't sound like a type system feature, for basically the same reason that type system features to create documentation descriptions doesn't exist. At the end of the day you can't add things to the type system that don't do anything because people will still find ways to observe the thing that's happening, and without some well-reasoned ordering of subtypes, that will cause a lot of unpredictable behavior.
from typescript.
Related Issues (20)
- ts80007 is incorrect at times? HOT 3
- Problems with __esModule marker in JS/TS mixed node16 environemnt HOT 3
- Error reported only in `node_modules` directory HOT 3
- Incorrect Chinese Translation for 'initializer' and Incorrect Use of Chinese Quotation Marks
- Shadowed import bindings require cross-file knowledge even with `isolatedModules` HOT 4
- Hover references/docs for JSX files (like for regular HTML and CSS files) HOT 7
- `noImplicitAny` infers `any` for typed parameter of union's common function HOT 2
- Wrapper Function that Runs Generic Function Doesn't Honor Generic Function Return Type HOT 2
- Memory Leak disposing oldProgram HOT 2
- A class with only getters satisfies some type without checking for the possibility of changing these fields HOT 2
- "Output generation failed" when transpiling "test.d.abc.ts" HOT 4
- Type literals in declaration files are emitted with comment blocks from the wrong source file
- Declaration emit of private properties should strip jsdoc
- 需要一个更为简单的ts HOT 2
- Possibly undefined type is not correctly detected in async code HOT 2
- checkJs finds hundreds of errors in .JS produced by TypeScript itself HOT 6
- TS7018 error without file and line number HOT 6
- JSDoc tags get lost when inheriting from a grandparent class
- Smarter String includes/endsWith/startsWith using template literal type predicates HOT 3
- Typed key accessor fails to infer type when used with generic HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from typescript.