What could be causing the error related to "Implicit any return type" in this situation?

I expect the code below to pass the type check successfully:

class MyClass<T extends object, P extends string = string> {
    method(thing: Thing) {
        return thing.method(this);
    }
}

declare class Thing {
    method(entity: MyClass<any>): void;
}

However, the method in MyClass is highlighted in red with the following message:

(method) MyClass<T extends object, P extends string = string>.method(thing: Thing): any
'method' 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.(7023)

Link to Playground

If this is a TypeScript bug, I will report it on their GitHub issue tracker, but I would appreciate hearing your thoughts first. Thank you.

Answer №1

Deciding whether to raise an issue on GitHub is ultimately up to you, but it is likely that the issue would be closed due to being classified as either a design limitation or functioning as intended. You can refer to microsoft/TypeScript#38724 and microsoft/TypeScript#35546 for similar cases, or you can search for the specific term in the issue tracker. Usually, when the compiler warns about circularity, it is because the type inference algorithm would lead to an infinite regress if it continued. This implies that there is indeed a circular reference present. Whether an average person could comprehend this without getting stuck in the same loop is not particularly relevant:

This situation is inherently circular, and the ability to reason our way out of it does not negate that fact. The core checking algorithm lacks the mechanisms needed to resolve this circularity.


In this scenario, I am drawing insights from microsoft/TypeScript#38724 and this particular comment:

This remains a circularity; in order to validate the type assertion from Object.assign(nation, this) to Nation, TypeScript must determine the type of this, which relies on the return type of clone.

Based on my analysis, here is a potential issue explanation for your case.

  • The compiler must deduce the return type of
    MyClass<T>.method(thing: Thing)
    .
  • To achieve this, it must know the return value of thing.method(this).
  • For this, it must resolve the call signature for thing.method() considering the parameter this.
  • This leads to examining the call signature for Thing.method(), where the parameter type is MyClass<any>, requiring confirmation if this can be assigned to MyClass<any>.
  • Subsequently, it must verify that the return type of this.method() is assignable to MyClass<any>.method()'s return type.
  • This process necessitates understanding the return type of MyClass<T>.method().

This circularity is causing the compiler to encounter issues. While my explanation is speculative, someone with deeper compiler knowledge could review and correct any inaccuracies. The crucial point to note is that even if it seems obvious to us that the return type of thing.method(this) is void, the compiler cannot easily process such observations due to hitting a circularity.


What bothers me about this type of response is that it implies that any use of this within a class without comprehensive annotations should prompt the compiler to flag circularities. The this type inherently introduces circular references. Yet, in practice, the compiler often overlooks such circular dependencies. Moreover, minor code alterations can magically eliminate the error:

class MyClass<T> {
    method(thing: Thing) { // no error now
        const ret = thing.method(this);
        return ret; 
    }
}

Presumably, this discrepancy is linked to the precise sequence of operations in the type inference algorithm, tailored to address common scenarios. Therefore, if you can present a compelling argument for your specific use case, you might consider submitting it as a suggestion rather than an issue, potentially avoiding immediate closure. However, it is unlikely that the matter will receive significant attention, especially considering that it can be easily resolved with a type annotation:

class MyClass<T> {
    method(thing: Thing): void { // annotate
        return thing.method(this);
    }
}

Test the code on TypeScript Playground

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the most suitable data type to represent an empty object?

When I declared the return type of the function below as {}, eslint flagged an error stating not to use {} as a type because it actually means "any non-nullish value". After understanding the meaning behind this error, I realize that specifying return typ ...

The 'xxx' type is lacking various properties compared to the 'xxx[]' type, such as length, pop, push, concat, and many others

Utilizing typescript and reactjs, the issue lies within this component import type { InputProps } from "../utils/types" const Input = (props: InputProps) => { const makeChildren = () => { return ( <> ...

What is the process for creating static pages that can access local data within a NextJS 13 application?

I recently completed a blog tutorial and I must say, it works like a charm. It's able to generate dynamic pages from .md blog posts stored locally, creating a beautiful output. However, I've hit a roadblock while attempting what seems like a sim ...

What could cause my arguments to "not align with any signature" of console.log?

Here is a basic class example: export class Logger { constructor(private name: string) {} debug(...args: any[]) { console.debug(...args) } log(...args: any[]) { console.log(...args) } } Despite being able to pass anything to console.l ...

The error TS2339 occurs because the property 'remove' is not found in the type 'Document<unknown>'

I encountered an error while using my application Runtime Error: TSError: ⨯ Unable to compile TypeScript: src/controllers/notes.ts:134:20 - error TS2339: Property 'remove' does not exist on type 'Document<unknown, {}, { createdAt: Nat ...

Why is NestJs having trouble resolving dependencies?

Recently delving into NestJs, I followed the configuration instructions outlined in https://docs.nestjs.com/techniques/database, but I am struggling to identify the issue within my code. Error: Nest cannot resolve dependencies of the AdminRepository ...

Tips for bypassing arrow functions when sending prop values to another component?

**Stateful ApplicatorType Component** class ApplicatorType extends Component { public state = { applicatorTypes: ['Carpenter', 'Painter', 'Plumber'], applicatorTypesSelected: [], } public render() { allotedTypes = ( &l ...

Can a unique intrinsic type be created from scratch?

Ever since template literals were introduced in Typescript (PR), we've had access to various useful functions in our types: Uppercase Lowercase Capitalize Uncapitalize For more information, refer to the official documentation. Although it may seem ...

What is the correct way to destructure a tuple in Typescript when only certain values will be assigned to new variables?

When writing code, I frequently encounter situations that resemble the following: function example(parameter: string) { const tuple = [ "newParameterValue", "newVariableValue" ] let newVar; [parameter, newVar] = tuple; } ( ...

The functionality of TypeScript's .entries() method is not available for the type 'DOMTokenList'

I'm currently working with a stack that includes Vue3, Vite, and TypeScript. I've encountered an issue related to DOMTokenList where I'm trying to utilize the .entries() method but TypeScript throws an error saying Property 'entries&apo ...

An array that solely needs a single element to conform to a specific type

While I was pondering API design concepts, a thought crossed my mind. Is it feasible to define a type in this manner? type SpecialArray<Unique, Bland> = [...Bland[], Unique, ...Bland[]]; However, the error message "A rest element cannot follow anoth ...

React Routing: Unleashing the Power of Multi-Level Routing

In my quest to create a route with multiple levels (<Route path="/hello/world" element={<a>hello world</a>} />), I encountered a few issues. Here are the versions I am using: react: 18.1 react-router-dom: 6.3.0 Success with O ...

Is there a possibility in TypeScript to indicate "as well as any additional ones"?

When working with typescript, it's important to define the variable type. Consider this example: userData: {id: number, name: string}; But what if you want to allow other keys with any types that won't be validated? Is there a way to achieve thi ...

Should I opt for 'typeof BN' or the BN Constructor when working with TypeScript and "bn.js"?

Note: Despite the recommendation to use BigInts instead of bn.js, I am currently working with a legacy codebase that has not been migrated yet. Below is the code that compiles and executes without any issues: import { BN } from "bn.js"; import a ...

The specified target "TypeScriptClean" is not present within the project

I'm facing some issues in Visual Studio 2017 Professional. Despite not having any TypeScript code in my solution, I am encountering numerous TypeScript-related errors during the build process. The main error message that keeps popping up is: The targ ...

How do I designate the compiled migration location?

Currently, I am utilizing the PostgreSQL database ORM Sequelize along with TypeScript as a backend script within the Express Node.js environment. My first inquiry is: Is it possible to directly create a model in .ts format? The second question pertains t ...

The jquery methods might encounter an issue with an undefined object

I have been attempting to implement a function that triggers when the user reaches the bottom of the window, but TypeScript is flagging errors and mentioning potential undefined objects related to window.scrollTop(), height(), and document.height(). Even ...

Error message: "The toJSON method is not found for the item in the nested array of

Encountering an issue with NSwag in my Angular project where it throws an error when attempting to send data if the object contains a nested array of objects like this: export interface IJobAdDto { mainJobAd: JobAddDetailsDto; differentLanguageJobA ...

Resolving the error message "Default props must have construct or call signatures for 'Component' in Typescript"

I'm currently working on a function component called MyComponent and I'm facing an issue with setting a default prop for component. The goal is to have the root node render as a "span" if no value is provided. However, I am encountering the follo ...

"ENUM value is stored in the event target value's handle property

My issue lies with the event.target.value that returns a 'String' value, and I want it to be recognized as an ENUM type. Here is my current code: export enum Permissions { OnlyMe, Everyone, SelectedPerson } ... <FormControl> & ...