Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Passing default props info through a HOC using TypeScript 3.1.x
import * as React from 'react';
type Omit<T, K extends keyof any> = T extends any ? Pick<T, Exclude<keyof T, K>> : never;
type ExtractProps<TComponentOrTProps> = TComponentOrTProps extends React.ComponentType<
infer P
>
? P
: never;
interface InjectedProps {
injected: boolean;
}
export const withInjector = <
TComponent extends React.ComponentType<InjectedProps & ExtractProps<TComponent>>
>(
WrappedComponent: TComponent
) => {
type WithInjectorProps = JSX.LibraryManagedAttributes<
TComponent,
ExtractProps<TComponent>
>;
return class extends React.Component<Omit<WithInjectorProps, keyof InjectedProps>> {
static displayName = `withInjector(${WrappedComponent.displayName})`;
render() {
// Coercing this makes us able to use it as JSX.
const CoercedWrappedComponent = WrappedComponent as React.ComponentType<InjectedProps & ExtractProps<TComponent>>;
return (
// works
<CoercedWrappedComponent injected {...this.props} />
);
return (
// [ts] JSX element type 'WrappedComponent' does not have any construct or call signatures.
<WrappedComponent injected {...this.props} />
);
}
};
};
@tkryskiewicz

This comment has been minimized.

Copy link

commented Jan 14, 2019

This is great! Thanks!

Seems that getting hocs to work with default props without infer isn't currently possible. The only thing I'd like to get rid of is this coercing... :)

@madou

This comment has been minimized.

Copy link
Owner Author

commented Jan 18, 2019

Np :)

@horvathgyozo

This comment has been minimized.

Copy link

commented Jan 18, 2019

As I see, it doesn't work with TypeScript 3.2.2. It says for the CoercedWrappedComponent:

Type '{ injected: true; } & Readonly<{ children?: ReactNode; }> & Readonly<Omit<LibraryManagedAttributes<TComponent, ExtractProps<TComponent>>, "injected">>' is not assignable to type 'IntrinsicAttributes & InjectedProps & ExtractProps<TComponent> & { children?: ReactNode; }'.
  Type '{ injected: true; } & Readonly<{ children?: ReactNode; }> & Readonly<Omit<LibraryManagedAttributes<TComponent, ExtractProps<TComponent>>, "injected">>' is not assignable to type 'ExtractProps<TComponent>'. [2322]
@madou

This comment has been minimized.

Copy link
Owner Author

commented Jan 24, 2019

ah that's a shame. I guess something has changed in the latest minor version. were you able to work through it?

@bolivier

This comment has been minimized.

Copy link

commented Feb 1, 2019

How is this possible: <TComponent extends React.ComponentType<InjectedProps & ExtractProps<TComponent>>>?

Shouldn't TComponent not be available at ExtractProps?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.