-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Throw types #40468
Throw types #40468
Conversation
@typescript-bot pack this |
Hey @orta, I've packed this into an installable tgz. You can install it for testing by referencing it in your
and then running There is also a playground for this build. |
Idea: Find a way to "match" the error string into the typescript diagnostic object, to reuse the translation of diagnostic message. A possible solution:
That will match the Diagnostic.Did_you_mean_0 and therefore it will be automatically translated by the compiler. |
Idea: Find a way to emit other kinds of diagnostic, like suggestions or warning. If so, there should be another mechanism to offer a underlying type like
|
Oh I just realized we can throw a object type so it can include more details! Please help me to investigate the possibility of this to find a good shape of the error object. Possible properties:
|
src/compiler/diagnosticMessages.json
Outdated
@@ -3032,6 +3032,10 @@ | |||
"category": "Error", | |||
"code": 2793 | |||
}, | |||
"Type instantiated results in a throw type saying: {0}": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something shorter? Type instantiation threw. {0}
?
Idea: Allow throw type to be handled by conditional type. This allows some error recovery or composing multiple errors. T extends throw infer E1 ?
U extends throw infer E2 ?
throw `\n ${E1}\n ${E2}`
: T : never |
import type { DiagnosticCategory } from 'typescript'
/**
* Since this is a type-level thing, any union in this type is considered invalid value
* cause their value is not determinate yet.
*
* `throw "string"` is convert to `throw { message: "string" }`
*/
type ErrorMessage = {
/**
* ! implemented !
* If diagnostic is not exist or not valid (key not found / not a tuple) this message will be used
*
* If it is not a string literal type, it will be formatted by `getTypeNameForErrorDisplay`
*/
message: any
/**
* What type should this throw type compatible(equal) with?
* Useful to "add" diagnostic message on a type and preserve itself
* @default never
*/
type?: any
/**
* ! implemented !
* TODO: provide completion for this in the language service
* Actually it is `[keyof Diagnostic (a @internal variable of ts), ...any[]]`
* @example ["_0_expected", T] results in "T expected" (with translation in different languages)
*/
diagnostic?: [type: string, ...args: any[]]
/**
* ! implemented !
* @default `Error` when undefined. `Message` when value is invalid.
*/
category?: 'suggestion' | 'error' | 'warning' | 'message'
/**
* It seems like deprecated is not in the DiagnosticCategory
*/
deprecated?: boolean
// ! Let developers custom the error code might not a good idea.
// code: number
/**
* When it happened on an identifer, replace the identifier with the suggestion
* e.g.: name => window.name
*
* When it happened on a type alias, do nothing
* When it happened on a CallExpression, do nothing
*
* ? Is this really useful cause the throw cannot get the original source text ?
*
* If we have higher kind types, this option can receive a un-instantiated generic type
* as a type-level function.
*
* @example
* type MyError<Context extends ...> = ...
* type T<U> = ... extends ... ? ... : throw {message: ..., suggestion: MyError}
*/
suggestion?: string
/**
* Let message be able to chain
*/
next?: ErrorMessage | ErrorMessage[]
} |
|
To be honest the initial idea is great - but adding diagnostics types and formatting feels like an overkill. It might even step into the linters world. The syntax is more complex too. I think having the ability to throw is already great as is. |
Hmm, I didn't introduce a new syntax for a "detailed" throw. It's a plain object literal type. I need some advice from the TypeScript team. If they think it's no need to do this, I'll stop working on that feature sets and focus on what will be accepted. Now I still have two complex ideas:
Is there anything I mentioned above that the TS team doesn't want? cc @RyanCavanaugh @orta @Kingwl |
Should the playground link posted by @typescript-bot be able to run the examples in the PR description? I'm not able to see the error messages as in the screenshot |
Oh, I'm sorry it's a regression (bug) @tom-sherman I'll fix it soon. You can try an old version https://www.staging-typescript.org/play?ts=4.1.0-pr-40402-15 (but it has other bugs) |
@Tschrock your case is interesting. currently throw type is not assignable to never type, I will revisit it next time I change this PR. |
Attempts to produce a helpful error message when invalid codecs are passed to `httpRequest`. It is a workaround until something like microsoft/TypeScript#40468 is merged.
I'm excited to see that this is still being (somewhat) actively developed. As a library developer, I would absolutely love to see this land. Any idea how to get the necessary attention for this to move forward? |
It always excites me when you are looking for a feature and some devs have been working on it for years. Yes I would love a "throw" type because some type checks require extraneous chaining of type generics and it can be hard to deliver semantic reasoning |
@DanielRosenwasser Is it possible to get a quick update on the team's plans for this PR? It has received a lot of interest and support from the community and been open for over 2 years now. The author recently stated:
While his diligence is admirable, he's kind of in a difficult spot having to continually make updates like this without any assurances as to when his work will be merged, if ever. @Jack-Works Just wanted to thank you for continuing to maintain this for so long! |
Just pointing out that the https://github.com/mmkal/expect-type TS type-checking library could really benefit from this PR if merged. @Jack-Works Thank you for creating this! Excited to hopefully use it! |
This is super nice. I have some questions - how (if) would the following constructs work? type T = throw "oops";
type U = "foo" | throw "oops";
type V = { a?: throw "oops" };
type W = (arg: throw "oops") => any;
type X<T> = T extends throw infer E ? true : false; Also, if I have Also, if I would suggest making What does everyone think? I suspect having good answers to all these questions is a way to help the PR move forward. |
@papb (rearranging your questions slightly)
If you look at the files changed in the PR, the tests show what the currently-proposed behavior is. That said, maybe @orta could ask the bot to set this up so that you could try them out in the playground? My understanding (of what at least I'd want) is that
I would hope all of these would immediately error.
This seems maybe problematic. I can see some value to being able to introspect the errors (particularly for library API testing), but I'd be inclined to move forward without it and really just make it an exact
I would hope so. In
TypeScript already treats type mismatches in a particular way, e.g. if you write
I don't think "subtype of never" is really a concept we want to open up here. The whole point of |
i'd assume that's intended to behave as a type level (of course, definitely a good idea to figure out how useful it would actually be in practice) |
Just wanted to bump this up. |
My thought is that by the time there's something to "catch", it's already too late - the error has been emitted. Using |
Agree that catching it in typing doesn't make sense. It's a little surprising for me to think about it being recoverable in conjunction with a |
close for housekeeping. I still have interest in this feature, so I will re-open and rebase it if the TS team also has an interest in it and give some suggestions of its type behavior. thanks for everyone watching & testing this PR! |
@Jack-Works Your work is very much appreciated! Wanted to take the chance to underscore that since this PR was created in 2020, the most popular libraries in the ecosystem have invested even further in advanced TS features to create the rich DX many devs have come to expect. Generics that perform some kind of input validation are a common manifestation of this trend, and unfortunately, most library authors end up resorting to TS's builtin solution, While some libraries like ArkType have started returning custom error messages instead, the problems I mentioned in my original comment still apply, and the fact that it feels like a hack likely deters a lot of authors from returning anything other than If there is something about this solution in particular that is unsatisfactory, it would be really useful to at least have an idea of what it is so that going forward contributors can avoid repeating it. I can't help but feel a bit sad seeing high-quality contributions like this languish. Everyone involved would greatly benefit from even a very brief explanation of the team's stance. |
Damn, this is a travesty :/ |
Fixes #23689
Playground: https://www.staging-typescript.org/play?ts=4.2.0-pr-40468-44
This PR introduces:
throw type_expr
. Currentlythrow
type only throws when it is being instantiated.TypeToString
to print a type.Considered use cases:
Welcome to suggest more use cases!
TypeAlias instantation
Prevent CallExpression
Prevent use of identifiers