It turns out that withBemMod typings I've introduced in #586 (and hotfixed in #588) don't work quite as expected.
With the new typings withBemMod doesn't work properly with compose anymore. compose(a, b, ...) results in Composition<any> instead of Composition<PropsA, PropsB, ...>:
interface IComponentProps {
theme?: 'normal';
view?: 'default';
}
const withTheme = withBemMod<IComponentProps>('Component', { theme: 'normal' });
const withView = withBemMod<IComponentProps>('Component', { view: 'default' });
// In 3.0.1 the type of withMods would be Composition<IComponentProps, IComponentProps>
// but in 3.0.2 it is Composition<any>
const withMods = compose(withTheme, withView);
As I figured out, Composition<any> is just a fallback after a list of proper overloads:
export type HOC<T> = (WrappedComponent: ComponentType) => ComponentType<T>
export function compose<T1>(fn1: HOC<T1>): Composition<T1>
export function compose<T1, T2>(fn1: HOC<T1>, fn2: HOC<T2>): Composition<T1 & T2>
// a couple more similar overloads up to 8 arguments
export function compose(...fns: Array<HOC<any>>): Composition<any>
The reason for the issue is that the new typings are a little too honest in their way of handling refs.
I've made three overloads of withBemMod: one for class components, one for ref forwarding function-ish components, and one for regular function components:
Every one of these returns a component with a ref prop, except for the last one, – it seemed like a good idea to me, since React does not support refs for function components. But because of that withBemMod doesn't return a HOC<T> anymore, since it's not determined whether or not T has a ref property. So only the Composition<any> overload is applicable for the new withBemMod typings.
One way to fix this is to make typings more loose and make a withBemMod-modified component to always have a ref prop. But it doesn't look like a safe solution to me – it might make the library users to pass refs to function components by mistake without a typechecker warning.
So I've come up with a fix with more strict typings: #593. Basically, it reverts typings to 3.0.1, but keeps the ref forwarding. It might seem hacky, but at least it doesn't break anything.
It turns out that
withBemMod
typings I've introduced in #586 (and hotfixed in #588) don't work quite as expected.With the new typings
withBemMod
doesn't work properly withcompose
anymore.compose(a, b, ...)
results inComposition<any>
instead ofComposition<PropsA, PropsB, ...>
:As I figured out,
Composition<any>
is just a fallback after a list of proper overloads:The reason for the issue is that the new typings are a little too honest in their way of handling refs.
I've made three overloads of
withBemMod
: one for class components, one for ref forwarding function-ish components, and one for regular function components:Every one of these returns a component with a
ref
prop, except for the last one, – it seemed like a good idea to me, since React does not support refs for function components. But because of thatwithBemMod
doesn't return aHOC<T>
anymore, since it's not determined whether or notT
has aref
property. So only theComposition<any>
overload is applicable for the newwithBemMod
typings.One way to fix this is to make typings more loose and make a
withBemMod
-modified component to always have aref
prop. But it doesn't look like a safe solution to me – it might make the library users to pass refs to function components by mistake without a typechecker warning.So I've come up with a fix with more strict typings: #593. Basically, it reverts typings to 3.0.1, but keeps the ref forwarding. It might seem hacky, but at least it doesn't break anything.