Skip to content

JSDoc: params for typed function are inferred as any #16220

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

Closed
OliverJAsh opened this issue Jun 2, 2017 · 7 comments
Closed

JSDoc: params for typed function are inferred as any #16220

OliverJAsh opened this issue Jun 2, 2017 · 7 comments
Labels
Duplicate An existing issue was already created

Comments

@OliverJAsh
Copy link
Contributor

OliverJAsh commented Jun 2, 2017

TypeScript Version: 2.3.4

Code

{
  /** @type {function(string): string} */
  const foo = x => x; // <-- x is inferred as any, expected string
  foo(1);

  // However, this works when using @param instead of @type
  /** @param {string} x */
  const foo2 = x => x; // <-- x is inferred as string
  foo2(1);
}
@OliverJAsh OliverJAsh changed the title JSDoc: server shows type as any when using @type JSDoc: params for typed function are inferred as any Jun 2, 2017
@mhegazy
Copy link
Contributor

mhegazy commented Jun 2, 2017

looks like a duplicate of #15618 (comment), the contextual type from the @type declaration is not flowing correctly to the lambda.

@mhegazy mhegazy added the Duplicate An existing issue was already created label Jun 2, 2017
@OliverJAsh
Copy link
Contributor Author

OliverJAsh commented Jun 13, 2017

This also appears to be effecting classes:

import React, { Component, ComponentClass } from 'react';

/** @typedef { {
    foo: string,
  } } Props */
/** @type {ComponentClass<Props>} */
const MyComponent = class extends Component {
  componentDidMount() {
    this.props.foo; // <-- foo is inferred as any, expected string
  }
};

<MyComponent foo={1} /> // <-- error as expected: 1 is not assigned to string

@mhegazy Is this the same bug as above, or does it need filing separately?

@mhegazy
Copy link
Contributor

mhegazy commented Jun 13, 2017

@OliverJAsh
Copy link
Contributor Author

OliverJAsh commented Jun 13, 2017

Thanks @mhegazy.

How come inference works with that syntax but not with @type? With the latter, type checking does work when the component is invoked, but the type doesn't appear to flow through the class.

To be clear, the example I gave uses a class expression, not a class declaration, so I can't see why @type wouldn't work just like a type annotation in TypeScript syntax:

const MyComponent: ComponentClass<Props> = class extends Component<any, any> {}

@mhegazy
Copy link
Contributor

mhegazy commented Jun 13, 2017

it is not really a type that is missing, it is that React.component is a generic class. without an explicit type parameter they default to any. @augments tells the type system to instantiate that class with the provided type parameters.

@OliverJAsh
Copy link
Contributor Author

OliverJAsh commented Jun 14, 2017

Thanks! That fixes it.

For context, the reason I am using the ComponentClass type as well as Component is because ComponentClass enforces type checking of the static properties on the class, such as displayName. Luckily, I can use @type and @augments on the class expression:

import React, { Component, ComponentClass } from 'react';

/** @typedef { {
    foo: string,
  } } Props */
/** @type {ComponentClass<Props>} */
/** @augments {Component<Props, any>} */
const MyComponent = class extends Component {
  componentDidMount() {
    this.props.foo; // <-- foo is inferred as string
  }
};

MyComponent.displayName = 1;  // <-- error as expected: 1 is not assignable to string

<MyComponent foo={1} /> // <-- error as expected: 1 is not assignable to string

This is equivalent to the following TypeScript:

import React, { Component, ComponentClass } from 'react';

type Props = {
  foo: string,
};
const MyComponent: ComponentClass<Props> = class extends Component<Props, any> {
  componentDidMount() {
    this.props.foo; // <-- foo is inferred as string
  }
};

MyComponent.displayName = 1;  // <-- error as expected: 1 is not assignable to string

<MyComponent foo={1} /> // <-- error as expected: 1 is not assignable to string

Given that this effects anyone who wants to use TypeScript with React, I'm wondering if there's any way to consolidate these two types into one, somehow: DefinitelyTyped/DefinitelyTyped#16967

I also mentioned this in this issue: #14600 (comment)

@OliverJAsh
Copy link
Contributor Author

Just tested on typescript@2.4.1-insiders.20170614 and this is fixed. Thanks!

@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants