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
Rule proposal: no-unnecessary-type-annotation #295
Comments
This already exists: |
I believe that's a different rule. What I'm suggesting is avoiding extraneous type annotation not assertion. |
I see. The variable declaration part fits into We don't have anything specific for function arguments yet though. |
I think it makes sense to split this into multiple rules. The most useful one for React is to warn against extra typing const Component: React.SFC<{foo: string}> =
({ foo }: { foo: string; children: React.ReactNode }): React.ReactElement<any> | null => (<div />); The parameter and return type annotations are redundant. I suggest we make a specific rule for this. Not sure how to name it. question |
The reason I say that the return type piece belongs in It seems weird to put the functionality to check for an unnecessary return type into a new rule - this would create a possible state where two rules can conflict: you would have That would suggest that we should duplicate logic into Potentially it's worth renaming the rule entirely (to something like |
okay, that makes sense. So I think to make this suggested rule's scope even narrower we can focus on parameters of a typed function expression (not function declarations) and leave return types to We can name it fs.readFile('file' , (err: NodeJS.ErrnoException) => {})
// ^__ unnecessary type annotation |
In general, what I'd want is a rule that errors when there's an explicit type that, once removed, results in an identical inferred type - in any context. |
I came here actually looking for the opposite rule - ensuring that all of my inferred types are explicitly typed. Normally I prefer to allow TypeScript to infer the types, but when working on open source libraries, I find it a lot more useful to be explicitly typed. People who come along after me know the intent more clearly, and reading code on pull requests/github is sure easier when the types are explicit. I was hoping that |
How about a name like |
We'd find this useful. Example is a factory function for a Koa middleware: export default (): Middleware => (
async (context: Context, next: Next): Promise<void> => {
... The export default (): Middleware => (
async (context, next) => {
... |
@mohsen1 are you still interested in working on this? If not, I can! |
Just as a note - there is a large problem with implementing this rule - namely that TS has no API to say "give me the type of this thing before annotation". You can (in a way) do this manually by comparing the type of the thing and the type of the annotation. There are a number of cases where TS doesn't do a good job of reporting the "actual" type of an expression (examples from One such example is when a generic is used in a return type position. In this case, TS will infer the type of the generic based on the contextual destination of the value. declare function foo<T = number>(): T;
const x: string = foo(); The type of What this means is that if you inspect the type of the variable, you'll get This is a bit of an anti-pattern in TS - generics shouldn't ever just be used in return value locations, but there are seemingly valid patterns where it can happen as well. I'm not arguing against this rule, I'm just dumping some knowledge that will need to be encoded in the rule's logic (/ included in the docs). |
TypeScript has similar logic in the extract to constant refactor: https://github.com/microsoft/TypeScript/blob/master/src/services/refactors/extractSymbol.ts#L1098-L1100. It is using |
I actually have a somewhat workable prototype of this working here: https://github.com/JoshuaKGoldberg/TypeStat/blob/166ab6c118ca611b0e6e37a73ebb9a225dad4b45/src/mutators/builtIn/fixNoInferableTypes/index.ts |
@JoshuaKGoldberg - your implementation isn't much different to the |
Two years after writing this I came to understand writing type annotations is helpful to TypeScript's performance. |
@mohsen1 can you expand on how it helps TS performance? Compilation, type detection in VS Code, etc? Also, I thought this issue was tracking expanding the rule from primitives to potentially all types when the language service can infer it. If not, I can open a new issue for that assuming it's possible. |
This can be a very complicated rule so I thought I open an issue discussing it before starting to work on it.
The idea is, when a type is inferred we should not have extra annotation.
Use Cases
There are many places in TypeScript that we can have extraneous type annotation. This list is probably not complete:
Variable declaration
Function arguments of a typed function
Return type annotation
The text was updated successfully, but these errors were encountered: