-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
feat(eslint-plugin): [ban-types] allow banning null and undefined #821
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
Conversation
Thanks for the PR, @Validark! typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community. The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately. Thanks again! 🙏 Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently on https://opencollective.com/typescript-eslint |
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.
thanks for your contribution!
While you're at it, could you please do two things:
- add support for
undefined
as well (I see no reason to not to have mirrored support forTSUndefinedKeyword
) - add tests
null
as a banned type in ban-types rulenull
as a banned type
My understanding is that The There's a reasonable case that
In JavaScript, the And it's problematic to allow both The obvious solution is to say "Okay, But there's two obstacles to that plan:
Thus, we cannot categorically ban Instead, what we really want is a lint rule that prevents new introductions of In other words: // This should be a lint error:
const x: string | null = null;
// This should NOT be a lint error:
const y: string | null = JSON.parse('null'); That is what TSLint's no-null-keyword did, and I'm pretty sure it's what eslint-plugin-no-null does. @Validark In this light, maybe this PR isn't needed? Or if there are TypeScript-specific aspects to the problem, perhaps we should create a separate |
I understand your argument, but I don't think it's a bad thing to support all named types - including type keywords - with this rule (except for I wouldn't use the option personally, because I haven't found that there's any lost clarity from using both. I have seen codebases go the other way - never explicitly write out
|
Seems reasonable. |
I can see how someone might be able to ban this: let x = undefined; But how would they realistically be able to ban this? let x: string | undefined = y.z; As the PR is written currently, won't it apply to both forms? |
In my free time I'm one of the main developers for a TypeScript to Lua compiler, which is basically our way of adding types (and promises, built-in functional methods, classes, extra operators) to otherwise regular Lua development. We want to completely ban @bradzacher requested that I add in similar functionality for undefined, probably more out of completeness than usability. If a person was testing it, you'd want it to work, even if nobody ever wants to block undefined. |
Weird, but reasonable! 😁 |
I've seen people do things to emulate flow's maybe operator (and other languages' maybe meta types): // flow
const x: ?number; // type === number | null | undefined
// ts
type Maybe<T> = T | null | undefined;
const x: Maybe<number>; In which case banning At work I've pretty much never explicitly ever written the |
Interesting... But how would you write this without using class TreeNode {
public parent: TreeNode | undefined = undefined;
public readonly children: TreeNode[] = [];
public addChild(child: TreeNode): void {
if (child.parent !== undefined) {
throw new Error('Already has a parent')
}
this.children.push(child);
child.parent = this;
}
public removeChild(child: TreeNode): void {
const index = this.children.indexOf(child);
if (index >= 0) {
this.children.splice(index, 1);
child.parent = undefined; // <=== ??
}
}
} |
You'd need to write // eslint-disable-next-line @typescript-eslint/ban-types
type Maybe<T> = T | null | undefined; In flow you don't need to because class TreeNode {
// flow
public parent: ?TreeNode = undefined;
// ts
public parent: Maybe<TreeNode> = undefined;
// also valid ts but I hate it
public parent!: Maybe<TreeNode>; Then your check is: if (child.parent != null) {
// or
if (child.parent != undefined) { Because |
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.
code LGTM. Thanks for your contribution!
@bradzacher What about this line from my example: if (index >= 0) {
this.children.splice(index, 1);
child.parent = undefined; // <=== ??
} |
could use either If you really wanted to do it without referencing either, you could do Or you could technically accomplish it with this combination, but optional members on classes are weird, and I hate it. class TreeNode {
public parent?: TreeNode;
// ...
public removeChild(child: TreeNode): void {
// ...
delete child.parent;
}
} |
Thanks for taking the time to share these examples. It's somewhat obscure trivia, but very interesting to see all the different styles that developers use! |
Sorry for conflicts introduced by recent merges @Validark, looks like there might have been a build failure as well. Just let me know when this is synced back up and we'll get it merged, thanks a lot! |
Just following up again @Validark, barring the conflicts and build failure this is good to merge |
Sorry for the delay. I will fix this as soon as I can. Just got a lot of code writing on my to-do list and haven't had another chance to fix this up. I will address this as soon as I can. |
Sorry for taking so many months, haha. A lot has happened. Anyway, I updated this PR again to the latest master. I still can't get the tests to work, however. I really don't know what the problem is. |
@Validark - the current CI step that's failing is code formatting. See CI output here: |
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.
LGTM - thanks for seeing this through.
null
as a banned type
Allows ban-types to block the
null
type.Can be used like so: