Reputation: 38140
With the withBlueBackground
high order component I extend a function with a new shade
property. (from this medium post)
This shade
property should be either 'light'
or 'dark'
.
Unfortunately these typings won't help us with refactored or wrong props
definition.
I attached an example which won't warn although 'ORANGE'
matches neither 'light'
nor 'dark'
.
import * as React from 'react';
type ColorShade = 'light' | 'dark';
export interface InjectedBlueBackgroundProps {
backgroundColor: string;
}
interface WithBlueBackgroundProps {
shade?: ColorShade;
}
const getBlueShade = (shade?: ColorShade) => {
switch (shade) {
case 'dark':
return 'navy';
case 'light':
return 'skyblue';
default:
return 'blue';
}
};
const withBlueBackground = <P extends InjectedBlueBackgroundProps>(
UnwrappedComponent: React.ComponentType<P>
) =>
class WithBlueBackground extends React.Component<
P & WithBlueBackgroundProps
> {
render() {
return (
<UnwrappedComponent
{...this.props}
backgroundColor={getBlueShade(this.props.shade)}
/>
);
}
};
export default withBlueBackground;
// The following line should throw an type error but does not:
export const Demo = withBlueBackground((props: {shade?: 'ORANGE'}) => {
return <div>{props.backgroundColor}</div>
});
Is there any solution?
Upvotes: 1
Views: 2565
Reputation: 33
Some things that make the HOC-call seem strange to me are:
1) the access of this. inside the arrow function
2) The usage of a HOC as a Lower-order-component... accessing this.props.shade from the generic props of the HOC
Please note that you want to give some own props (top-level) and some injected props (low-level) to the wrapped component with only a single HOC.
// main.ts
import React from 'react';
import {Demo} from './demo';
React.render(
<Demo
greeting="hello"
shape="light"
/>,
document.getElementById('app'),
);
demo file
// demo.ts
import React from 'react';
import withBlueBackground, {InjectedBlueBackgroundProps, OwnBlueBackgroundProps} from './withBlueBackground';
interface OwnDemoProps extends OwnBlueBackgroundProps {
greeting: string;
}
type DemoProps = OwnDemoProps & InjectedBlueBackgroundProps;
const Demo = (props: DemoProps) => (
<div>{props.greeting + ' ' + props.backgroundColor}</div>
);
const DemoBlue = withBlueBackground<OwnDemoProps>(Demo);
export {DemoBlue as Demo};
hoc file
// withBlueBackground.ts
import React from 'react';
export type ColorShade = 'light' | 'dark';
const getBlueShade = (shade?: ColorShade) => {
switch (shade) {
case 'dark':
return 'navy';
case 'light':
return 'skyblue';
default:
return 'blue';
}
};
export interface OwnBlueBackgroundProps {
shade?: ColorShade;
}
export interface InjectedBlueBackgroundProps {
backgroundColor: string;
}
const withBlueBackground = <P extends OwnBlueBackgroundProps>(
UnwrappedComponent: React.ComponentType<P & InjectedBlueBackgroundProps>
) => class WithBlueBackground extends React.Component<
P & InjectedBlueBackgroundProps
> {
public render() {
return (
<UnwrappedComponent
{...this.props}
backgroundColor={getBlueShade(this.props.shade)}
/>
);
}
};
export default withBlueBackground;
Upvotes: 2