Skip to content
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: Disallow unions with unknown or any #3926

Closed
fregante opened this issue Sep 25, 2021 · 1 comment · Fixed by #4378
Closed

Rule proposal: Disallow unions with unknown or any #3926

fregante opened this issue Sep 25, 2021 · 1 comment · Fixed by #4378
Labels
accepting prs Go ahead, send a pull request that resolves this issue enhancement: new plugin rule New rule request for eslint-plugin package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin

Comments

@fregante
Copy link
Contributor

fregante commented Sep 25, 2021

Description

From what I understand, T | unknown and T | any resolve to just unknown and any respectively, so I don't think they're particularly useful.

However maybe it's still useful as suggested type documentation, because such types would still appear as X | unknown in some cases.

Thoughts?

Fail

type MaybeNumber = number | unknown;

function isNumber(value: number | any): value is number {
	return typeof value === 'number';
}

Pass

type MaybeNumber = unknown;

function isNumber(value: any): value is number {
	return typeof value === 'number';
}
@fregante fregante added package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for maintainers to take a look labels Sep 25, 2021
@bradzacher
Copy link
Member

I think that this would be pretty valuable.

There are the following cases for any, unknown, and `never:

  • any and unknown "override" all other union members:
    • any | 'foo' === any, unknown | 'foo' === unknown
  • any and never "override" all other intersection members.
    • any & 'foo' === any, never | 'foo' === never

And the two special cases:

  • unknown is dropped from intersections:
    • string & unknown === string
  • never is dropped from unions in any position EXCEPT when in a return type position:
    • type T = string | never === string but type T = () => string | never !== () => string

This is also cases for literal + primitive types:

  • primitive types "override" any literal types in a union:
    • string | 'foo' === string, number | 1 === number, boolean | false === boolean
  • literal types "override" any primitive types in an intersection
    • string & 'foo' === 'foo', number & 1 === 1, boolean & false === false

With so many cases and edge cases - this goes beyond just banning specific syntax - so I think this makes sense as an entire rule.

Maybe something like no-redundant-union-or-intersection-members?

@bradzacher bradzacher added enhancement: new plugin rule New rule request for eslint-plugin and removed triage Waiting for maintainers to take a look labels Sep 26, 2021
@JoshuaKGoldberg JoshuaKGoldberg added the accepting prs Go ahead, send a pull request that resolves this issue label Oct 25, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 25, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepting prs Go ahead, send a pull request that resolves this issue enhancement: new plugin rule New rule request for eslint-plugin package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants