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

Compiler is unable to resolve return type of function even though it is returning function with known return type #26623

Closed
devuxer opened this issue Aug 23, 2018 · 3 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@devuxer
Copy link

devuxer commented Aug 23, 2018

TypeScript Version: 3.0.1

Search Terms:

  • "implicitly has return type 'any'"
  • TS7023

Code

interface Identifiable {
    name: string;
    nickname: string;
    isNameSameAsNickname: boolean;
}

class Person implements Identifiable {
    public name = "Baz";
    public nickname = "Baz";

    get isNameSameAsNickname() {
        return compareNames(this);
    }
}

function compareNames(identifiable: Identifiable) {
    return identifiable.name === identifiable.nickname;
}

Expected behavior:

Compiles without error

Actual behavior:

The following error occurs:

TS7023: 'isNameSameAsNickname' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.

Comment: This error appears to be incorrect (or at least worded ambiguously) because isNameSameAsNickname is not referenced directly or indirectly in one of its return expressions. Specifically, isNameSameAsNickname does not appear directly in the return expression compareNames(this) nor does it appear indirectly in identifiable.name === identifiable.nickname.

Workaround:

Declare the return type explicitly:

get isNameSameAsNickname(): boolean {
    return compareNames(this);
}

Playground Link:

This error is indicated in the playground with a red squiggle below isNameSameAsNickname().

Note: Error only occurs if noImplicitAny option is checked

Related Issues:

@devuxer devuxer changed the title Returning a function with a known return type Compiler is unable to resolve return type of function even though it is returning function with known return type Aug 23, 2018
@RyanCavanaugh RyanCavanaugh added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Aug 23, 2018
@RyanCavanaugh
Copy link
Member

This is a circular operation, because we have to check what the type of Person#isNameSameAsNickname is in order to check the call to compareNames to figure out what the return type could be. You can see this because removing isNameSameAsNickname from Identifiable causes the error to go away.

@devuxer
Copy link
Author

devuxer commented Aug 23, 2018

@RyanCavanaugh,

Thanks for your reply. So it sounds like you are saying, the compiler is undergoing the following "thought" process:

  1. Okay, so isSameAsNickname depends on compareNames.
  2. And compareNames requires an Identifiable as input.
  3. And an Identifiable must have a property, isNameSameAsNickname, that returns a boolean.
  4. Therefore, compareNames depends on isNameSameAsNickname.
  5. Damn, this is complicated, I give up.

Meanwhile, the human being (me) is undergoing a different thought process:

  1. Okay, so isNameSameAsNickname depends on compareNames.
  2. And compareNames returns a boolean.
  3. Therefore isNameSameAsNickname must return a boolean.
  4. Therefore Person is a legitimate Identifiable.
  5. Therefore compareNames can be called.

This suggests that the order that type checks are performed has a significant effect on whether dependencies resolve or are deemed circular. On the surface, this seems like it shouldn't be hard to fix, but I gather it's a difficult problem or it would already be solved.

This does bring up a question...

The workaround I provided is obviously very simple to implement, so I'm OK using that, but is there a better, more "best practices" way to accomplish this type of thing that avoids this issue altogether?

@RyanCavanaugh
Copy link
Member

I gather it's a difficult problem or it would already be solved.

Yep 😉. The real issue here is that the two main operations the checker does - inference and error detection - occur at the "same time". You could imagine a different world where all inference happens, then all error checking happens, which would avoid this problem because the check of whether the argument type is assignable to the parameter type would only be part of the error-checking phase. But this would likely be at least twice as slow as the current implementation.

There's no set practice that will avoid all circularity issues. The return type annotation is the best alternative for this example, I would say.

rwaskiewicz pushed a commit to ionic-team/stencil that referenced this issue Oct 19, 2021
update typescript to v4.3.5

add type annotations to methods that have an implicit any type in TS 4.3 - for more information, see microsoft/TypeScript#26623

map TS 4.3+ `JSDocTagInfo` to `CompilerJsDocTagInfo` - for more information, see microsoft/TypeScript#43312

add type guard for `TestingSystem`. in TS 4.3, `Object.defineProperties` is now generic, and returns the same type `T` as it's first argument. adding a typeguard allows consumers of this method to ensure they're receiving a `TestingSystem` object

enable `noImplicitOverride` compiler flag
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

2 participants