Skip to content

Pipe function + React.memo returns component with any props #38930

Description

TypeScript Version: 3.9.2

Search Terms: generic pipe pipeWith react memo HOC props any

Code

import * as React from 'react';

declare function pipeWith<A, B>(a: A, ab: (a: A) => B): B;

type Props = { foo: number };
declare const MyComponent: React.FunctionComponent<Props>;

// ✅ correct props type
// React.NamedExoticComponent<Props>
const r1 = React.memo(MyComponent);

// ❌ `any` props type
// React.MemoExoticComponent<React.ComponentType<any>>
const r2 = pipeWith(MyComponent, React.memo);

// Workaround
// ✅ correct props type
// React.NamedExoticComponent<Props>
const r3 = pipeWith(MyComponent, (C) => React.memo(C));

Using latest version of @types/react (at the time of writing: 16.9.35).

Expected behavior:

See above.

Actual behavior:

See above.

Playground Link:

https://stackblitz.com/edit/react-ts-4ih6jn

Related Issues:

#25637, although that was closed as a duplicate of an issue which has since been closed (#10957), so I decided to post a new issue.

Activity

  1. RyanCavanaugh commented on Jun 12, 2020

    @RyanCavanaugh
    Member

    What's the definition of memo ?

  2. RyanCavanaugh commented on Jun 15, 2020

    @RyanCavanaugh
    Member

    If someone can provide an isolated repro we can investigate

  3. dragomirtitian commented on Jun 22, 2020

    @dragomirtitian
    Contributor

    Ryan Cavanaugh (@RyanCavanaugh) Hope this helps:

    // The presence of any overloads confuses inference, leave just one of them in and everything works
    declare function memo<T>(Component: T): T;
    declare function memo<T>(Component: T): T;
    
    declare function pipeWith<A, B>(a: A, ab: (a: A) => B): B;
    
    type Props = { foo: number };
    declare const MyComponent: Props;
    
    // ✅ correct props type
    // Props
    const r1 = memo(MyComponent);
    
    // ❌ `unknown` props type
    // unknown
    const r2 = pipeWith(MyComponent, memo);
    
    // Workaround
    // ✅ correct props type
    // Props
    const r3 = pipeWith(MyComponent, (C) => memo(C));

    Playground Link

    Just the presence of any overloads will confuse the inference on the original use case. Leave just the one signature and everything works as expected.

  4. 3 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs InvestigationThis issue needs a team member to investigate its status.RescheduledThis issue was previously scheduled to an earlier milestone

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions