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

unnecessary-optional-chain incorrectly reports warning #8065

Closed
lukeapage opened this issue Sep 9, 2019 · 7 comments
Closed

unnecessary-optional-chain incorrectly reports warning #8065

lukeapage opened this issue Sep 9, 2019 · 7 comments

Comments

@lukeapage
Copy link
Contributor

Flow version: 0.107.0

Expected behavior

No warnings

Actual behavior

Cannot try on flow.org/try as it does not allow configuration of lint rules.

// @flow

type State = {|
    base?: {|
        data: {|
            a: string,
        |},
    |},
|};

const getBase = (state: State) => state.base ?? {};

export const getA = (state: State) => getBase(state).data?.a;

gives the following warning:


Warning ---------------------------------------------------------------------------------- frontend/src/flowbug.js:14:39                                                                                                                                                                                                                                                  This use of optional chaining (?.) is unnecessary because getBase(...).data [1] cannot be nullish or because an earlier                                                              ?. will short-circuit the nullish case. (unnecessary-optional-chain)                                                                                                                                                                                                                                                                                                           11\| // : {\| data?: {\| a: string \|} \|}                                                                                                                                                12\| const getBase = (state: State) => state.base ?? {};                                                                                                                              13\|                                                                                                                                                                              [1] 14\| export const getA = (state: State) => getBase(state).data?.a;                                                                                                                    15\|
--

so if I try to fix it by adding explicit types, I get a new warning

// @flow

type State = {|
    base?: {|
        data: {|
            a: string,
        |},
    |},
|};

const getBase = (state: State): : {| data?: {| a: string |} |} => state.base ?? {};

export const getA = (state: State) => getBase(state).data?.a;

gives


Error ------------------------------------------------------------------------------------ frontend/src/flowbug.js:11:65                                                                                                                                                                                                                                                  Cannot return state.base ?? {...} because:                                                                                                                                            - inexact undefined [1] is incompatible with exact object type [2] in property data.                                                                                                 - inexact object literal [3] is incompatible with exact object type [4].                                                                                                                                                                                                                                                                                                        [2]  5\|         data: {\|                                                                                                                                                                  6\|             a: string,                                                                                                                                                            7\|         \|},                                                                                                                                                                       8\|     \|},                                                                                                                                                                           9\| \|};                                                                                                                                                                              10\|                                                                                                                                                                        [4][1][3] 11\| const getBase = (state: State): {\| data?: {\| a: string \|} \|} => state.base ?? {};                                                                                                12\|                                                                                                                                                                                  13\| export const getA = (state: State) => getBase(state).data?.a;                                                                                                                    14\|
--

and if I try a third possibility I get another existing bug

// @flow

type State = {|
    base?: {|
        data: {|
            a: string,
        |},
    |},
|};

const getBase = (state: State): {| data: {| a: string |} |} | {||} => state.base ?? {};

export const getA = (state: State) => getBase(state).data?.a;

gives


Error ------------------------------------------------------------------------------------ frontend/src/flowbug.js:11:85                                                                                                                                                                                                                                                  Cannot return state.base ?? {...} because:                                                                                                                                            - Either inexact object literal [1] is incompatible with exact object type [2].                                                                                                      - Or inexact object literal [1] is incompatible with exact object type [3].                                                                                                                                                                                                                                                                                                          8\|     \|},                                                                                                                                                                           9\| \|};                                                                                                                                                                              10\|                                                                                                                                                                        [2][3][1] 11\| const getBase = (state: State): {\| data: {\| a: string \|} \|} \| {\|\|} => state.base ?? {};                                                                                          12\|                                                                                                                                                                                  13\| export const getA = (state: State) => getBase(state).data?.a;                                                                                                                    14\|
--

this 3rd example is: #2977

this issue is possibly the same underlying bug as in #6613 except that its pretty normal to use the null coalescing operator with optional chaining.

@Hypnosphi
Copy link
Contributor

related: #8491

@TrySound
Copy link
Contributor

I think we got optional chaining and nullish coalescing to not do anymore hacks with fallback to empty object. You can return null instead and avoid unsealed object.
https://github.com/facebook/flow/issues?q=is%3Aopen+is%3Aissue+label%3A%22unsealed+objects%22

@Hypnosphi
Copy link
Contributor

@TrySound, this:

const {a, b, c, d, e, f, g} = getSmth() ?? {}

return {a, b, c, d, e, f, g} 

still looks better to me than that:

const smth = getSmth()

return {
  a: smth?.a,
  b: smth?.b,
  c: smth?.c,
  d: smth?.d,
  e: smth?.e,
  f: smth?.f,
  g: smth?.g,
}

My main usecase for this is mapStateToProps function from react-redux, where it's preferrable to return primitives as props

@gkz
Copy link
Member

gkz commented Oct 27, 2022

@gkz gkz closed this as completed Oct 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants