Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

Add no-unnecessary-type-assertion rule #2519

Merged
merged 5 commits into from
Apr 12, 2017
Merged

Conversation

mitchellwills
Copy link
Contributor

PR checklist

  • New feature, bugfix, or enhancement
    • Includes tests

Overview of change:

Adds rule that warns when a cast has no effect (the uncast expression has the same type as the cast expression).

Is there anything you'd like reviewers to focus on?

The tests are broken because the lint check typecheck is not running with strict null checks ("string|undefined" type gets reported as "string" by typechecker). Adding the strictNullChecks fixed this for me in an internal repo, but doesn't seem to work here for some reason (may be ts2.2 vs ts2.3?). Any ideas what needs to change to make it work?

I compare the two types using ===. From my testing this seems to work, but there doesn't seem to be any documentation that indicates this behavior can be relied on. Is there a preferred way to check the equality of types?

@palantirtech
Copy link
Member

Thanks for your interest in palantir/tslint, @mitchellwills! Before we can accept your pull request, you need to sign our contributor license agreement - just visit https://cla.palantir.com/ and follow the instructions. Once you sign, I'll automatically update this pull request.

Copy link
Contributor

@ajafff ajafff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the effort you put into this.
Long term we try to migrate all rules from RuleWalker to another walker design. Please refer to https://palantir.github.io/tslint/develop/custom-rules/walker-design.html for an explanation of the new concepts. Would you mind migrating your implementation?

In addition this rule needs tests for union types that are narrowed by type guards and/or a discriminant property

@mitchellwills
Copy link
Contributor Author

Sure i'll take a stab at the changes you suggested. Any idea on how to enable strict null types for the tests (I guess I could just switch it to a union type, but it would probably be good to test both)?

* Fix tests
* Add tests for union types with type guards and discriminant properties
* Migrate implementation to AbstractWalker
* Revert changes to src/language/walker/syntaxWalker.ts
@mitchellwills
Copy link
Contributor Author

Migrated to AbstractWalker and added/fixed tests

@andy-hanson
Copy link
Contributor

microsoft/TypeScript#13502 would make this rule much better. Presumably it won't warn for myCat as Animal now.

@mitchellwills
Copy link
Contributor Author

Hmm yah that would be pretty neat. I wonder if some people would still want to use a cast since there are some cases where removing those casts would cause errors.

let x = 'a' as string|number;
x = 5;

Although they should probably use let x: string|number = 'a';. Don't know if people actually do that

@mitchellwills
Copy link
Contributor Author

re CLA: I am covered under the Google corporate CLA. I just made my membership of the google organization public though and it doesn't look like there's a way for me to retrigger the CLA bot.

Copy link
Contributor

@adidahiya adidahiya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like a good rule. some changes requested. most important is the fact that these are type assertions, not casts (the latter implies some runtime behavior).


export class Rule extends Lint.Rules.TypedRule {
/* tslint:disable:object-literal-sort-keys */
public static metadata: Lint.IRuleMetadata = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: please use 4-space indentation (as per the root .editorconfig)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reformatted all the files

type: "typescript",
typescriptOnly: true,
requiresTypeInfo: true,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like you implemented a fixer. can you add hasFix: true to the metadata?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

};
/* tslint:enable:object-literal-sort-keys */

public static FAILURE_STRING = "This cast is unnecessary.";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please be more descriptive in the failure string and explain that the cast doesn't change the type of the expression. Also, to be slightly pedantic here (well within the rights of a linter), this is more correctly referred to as a type assertion in TS syntax, so let's refer to it as such (we have other rules that relate to type assertions). The name should be changed to no-unnecessary-type-assertion.

FAILURE_STRING = "This assertion is unnecessary since it does not change the type of the expression."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added suggested failure string and renamed the rule everywhere. The AST is a little misleading here since it refers to "expr" as a type assertion and the others as something else.

const castType = this.typeChecker.getTypeAtLocation(node);
const uncastType = this.typeChecker.getTypeAtLocation(node.expression);

if (uncastType && castType && uncastType === castType) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please avoid implicit type coercion to boolean (I'd like to turn on strict-boolean-expressions). do explicit null checks uncastType != null && castType != null && ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed implicit boolean coercion

* Replace references to cast with the more correct type assertion
* Fix formatting
* Improve metadata
@mitchellwills mitchellwills changed the title Add no-unnecessary-cast rule Add no-unnecessary-type-assertion rule Apr 12, 2017
@adidahiya
Copy link
Contributor

thanks @mitchellwills!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants