Preact: TypeScript definition render() problem

Created on 23 Aug 2017  路  13Comments  路  Source: preactjs/preact

https://github.com/developit/preact/blob/0dea3b77ee0677987815347c1e6bd23821728aa2/src/preact.d.ts#L66

So, this definition doesn't seem to work. I have to do something like this to make it work:

interface Props {
  item: any;
}

class Item extends Component<Props, any> {
  render({ item }: Props) {
    return <div class="item">
      {item.title}
    </div>;
  }
}
help wanted types

Most helpful comment

Yeah, this is a Typescript issue. Consider this minimal example in the TS playground:

screen shot 2018-02-17 at 05 42 09

In the above, this.props is correctly inferred to be of type Person.

Yet, the argument passed into the function - despite being part of the overridden function signature (TS will balk if you pass into a non-Person instance) - is incorrectly inferred as any:

screen shot 2018-02-17 at 05 45 13

Preact is doing the right thing in its type definitions; if/when TS fix it, it should just work.

Until then, your options are:

  1. Explicitly define the type in the render() args list, or...
  2. Use this.props.

FWIW, I do the latter. It means I define the types in one place and screw up less often, whilst also cleaning up the render() call (I never understood the point of explicitly passing in props, when they're already set on this.props anyway.)

All 13 comments

Think its a TS version thing? Personally I like the more open-ended version you have there but I know people like having strict defs for children, etc.

Probably. I'm laster Preact and TS for a new project.

That's just an example with any. I kinda prefer it without types at all, but feel like for a big project it's better for types. The problem there is it I cannot just do render({ item }) -- it doesn't recognise the type of the props passed to it, so I have to add the type manually (: Props thing).

I'm not a TypeScript definition pro and I actually have no idea how to fix it, so filed this issue.

^ exactly my feeling. TBH I'd rather have loose definitions (any) than have people run into cases where the definition is incorrect.

I do not think that ts can infer the types there. I rely on this.props in order not to redefine the props on every render function

The React types have the same issue, and get a lot of attention. Unless a future version of TypeScript comes out that supports this inheritance, this could probably be closed.

Yeah, this is a Typescript issue. Consider this minimal example in the TS playground:

screen shot 2018-02-17 at 05 42 09

In the above, this.props is correctly inferred to be of type Person.

Yet, the argument passed into the function - despite being part of the overridden function signature (TS will balk if you pass into a non-Person instance) - is incorrectly inferred as any:

screen shot 2018-02-17 at 05 45 13

Preact is doing the right thing in its type definitions; if/when TS fix it, it should just work.

Until then, your options are:

  1. Explicitly define the type in the render() args list, or...
  2. Use this.props.

FWIW, I do the latter. It means I define the types in one place and screw up less often, whilst also cleaning up the render() call (I never understood the point of explicitly passing in props, when they're already set on this.props anyway.)

Really hoping to see a fix for this 馃悪

mh... I can't reproduce this issue on the playground. The typings are correctly inferred there.

screen shot 2018-03-20 at 11 38 30

But somehow I can't get this to work with our typings. Will investigate further.

EDIT: Nevermind, I misread the above post.

Seems like this is the bug that we are encountering: https://github.com/Microsoft/TypeScript/issues/21734

As a follow up to those now coming to this issue, it seems (per the comment @marvinhagemeister posted) that this is the intended usage (issue was updated March 2019). So I guess we're stuck with:

render (props: Props, state: State) {}
//OR
render () {
  this.props...
}

I didn't think the render() method received props as an argument anymore?

(Why does it? You can already access them using this.props - why do we need a second way to do that?)

@mindplay-dk accessing this as a keyword always introduces extra overhead in terms of bundle size, this way you can surpass that hurdle.

Yeah, then you need the extra type-hint.

I've been bothered by this before - it's been a minor annoyance, nothing too grievous for me.

And it's just an annotation with no effect on bundle size, so... I just add it and move on.

(Incidentally, constructors also can't be abstracted and can't inherit anything - so you'll duplicate the type-hint for the props argument in constructors as well. It's not perfect.)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

paulkatich picture paulkatich  路  3Comments

Zashy picture Zashy  路  3Comments

nopantsmonkey picture nopantsmonkey  路  3Comments

simonjoom picture simonjoom  路  3Comments

marcosguti picture marcosguti  路  3Comments