Skip to content

Suggestion: Try to avoid forcing any type on types that reference themselves (especially around JSX) #22390

@kpdonn

Description

@kpdonn

Search Terms:

  • TS7023: 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.
  • TS7022: implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer
  • noImplicitAny
  • React, JSX, TSX, render

Code

import * as React from "react"

declare function create<T>(arg: { comp: React.ComponentClass<T> }): React.ComponentClass<T>

class MyComponent extends React.Component<any, any> {
  render() {
    return <div><GeneratedComp /></div>
  }
}

const GeneratedComp = create({
  comp: MyComponent
})

Current Behavior
In strict mode the code above will have noImplicitAny errors for GeneratedComp and render because they indirectly reference each other. The workaround today is to explicitly annotate the render function as returning something like React.ReactNode.

Desired Behavior
The code above would ideally compile without errors and GeneratedComp would have the expected ComponentClass<T> type instead of any type.

Motivation
I've been playing around with an idea for a typescript routing library that would dynamically generate statically typed link components as you configure it, but actually using that link component naturally requires circular references which hits the behavior above. It's still just as easy to workaround by adding a type annotation to render, but if you forget to do that basically everything in the project starts having errors because of how intertwined it is.

Suggestion
I don't really know how to write up this suggestion beyond what I wrote in the "Desired Behavior" section above, so instead I put together a rough proof of concept of how allowing these types without explicit type annotations might work on a branch here. It isn't intended as a PR, my goal was just to get my example working any way I could to see if it was realistic. It appears it is at least possible so now the question is if this behavior would be considered desirable to add to Typescript.

Related Issues:
Some past issues I found that likely would start working with this type of change:
#17386
#16892
#11628
#8546
#5403

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixedA PR has been merged for this issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions