Skip to content

Instantly share code, notes, and snippets.

@fbartho
Forked from miloszpp/hoc.ts
Last active July 26, 2019 17:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fbartho/3973337d702e5d10b255d24f28d4f596 to your computer and use it in GitHub Desktop.
Save fbartho/3973337d702e5d10b255d24f28d4f596 to your computer and use it in GitHub Desktop.
Test that demonstrates the new Generic Propagation features available in TypeScript 3.4
import React from "react";
interface InjectedProps {
injected1: string;
}
interface PubProps<Foo> {
pubProp1: Foo;
}
declare function bind<T>(
component: React.ComponentType<T & InjectedProps>,
): React.ComponentType<T>;
declare class A<B> extends React.Component<PubProps<B> & InjectedProps> {}
const APrimeComponent = bind(A); // No good :(
// type inferred to: React.ComponentType<PubProps<unknown>>
declare function AFunc<B>(
props: PubProps<B> & InjectedProps,
): React.ReactElement;
const AFuncPrimeComponent = bind(AFunc); // No good :(
// type inferred to: React.ComponentType<PubProps<unknown>>
declare function bindHack<T>(
component: (props: T & InjectedProps) => React.ReactElement,
): (props: T) => React.ReactElement;
const AFuncPrimeComponentHack = bindHack(AFunc);
// type inferred correctly! AFuncPrimeComponentHack is generic
const render = () => <AFuncPrimeComponentHack pubProp1={5} />;
/// --------------------------------------------------------------------
interface PartialBinder<SomeOtherType> {
bind1: <T>(
component: (props: T & SomeOtherType) => React.ReactElement,
) => (props: T) => React.ReactElement;
bind2: <T>(
component: React.FunctionComponent<T & SomeOtherType>,
) => React.FunctionComponent<T>;
bind3: <T>(
component: React.ComponentType<T & SomeOtherType>,
) => React.ComponentType<T>;
}
interface DynamicInjectedProps {
meep: boolean;
}
declare class BComponent<C> extends React.Component<
PubProps<C> & DynamicInjectedProps
> {}
declare const BFuncComponent: <C>(
props: PubProps<C> & DynamicInjectedProps,
) => React.ReactElement;
declare const helper: PartialBinder<DynamicInjectedProps>;
const B1PrimeComponent = helper.bind1(BComponent); // Doesn't work -- error!
const B1FuncPrimeComponent = helper.bind1(BFuncComponent); // Yay! Success!
const B2PrimeComponent = helper.bind2(BComponent); // Doesn't work -- error!
const B2FuncPrimeComponent = helper.bind2(BFuncComponent); // type inferred to: React.ComponentType<PubProps<unknown>>
const B3PrimeComponent = helper.bind3(BComponent); // type inferred to: React.ComponentType<PubProps<unknown>>
const B3FuncPrimeComponent = helper.bind3(BFuncComponent); // type inferred to: React.ComponentType<PubProps<unknown>>
// Summary: Actual, bare, Function components are required for correct inference!
// React.FunctionComponent or React.ComponentType do *not* work!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment