typescript - Hur specificerar jag rätt returtyp för mapStateToProps?
I min mapStateToProps nedan skulle jag vilja ange en explicit TypeScript-returtyp:
interface CounterProps {
sequence: number;
count: number;
}
class Counter extends Component<CounterProps> {
public static defaultProps = {
sequence: 0,
count: 0
};
public render() {
const sequence = this.props.sequence
const count = this.props.count
return (
// Some use of sequence, count ...
)
}
}
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const mapStateToProps = (state: CounterState) => ({
count: state.count,
})
export default connect(mapStateToProps)(Counter)
Men den uppenbara lösningen att använda Partial med
const mapStateToProps = (state: CounterState): Partial<CounterProps> => ({
count: state.count,
})
misslyckas med TS2345 vid anropet av connect (Counter kan inte tilldelas den förväntade typen).
Alternativt, att göra den icke-returnerade medlemmen valfri med
interface CounterProps {
sequence?: number;
count: number;
}
tillåter
const mapStateToProps = (state: CounterState): CounterProps => ({
count: state.count,
})
att fungera, men resulterar i TS2352 (möjligen odefinierad) för alla användningar av sequence i render.
Hur specificerar jag rätt returtyp för mapStateToProps, som enligt specifikationen endast behöver returnera en delmängd av medlemmarna i den motsvarande typen?
Svar #1
Prova Pick<T, K>-hjälpverktygstypen
Eftersom du bara returnerar ett objekt med en enda egenskap "count" från CounterProps, borde du kunna använda Pick<CounterProps, 'count'> som returtyp för mapStateToProps.
Pick är också användbart när man anropar setState med en callback när man ändrar tillståndet baserat på det befintliga tillståndet. Till exempel:
interface ComponentState {
active: true;
something: number;
else: string;
}
class MyComponent extends React.Component<{}, ComponentState> {
constructor(props) {
super(props);
this.state = {
active: false,
something: 123,
else: 'hello world',
};
}
toggle(): void {
this.setState((state: ComponentState): Pick<ComponentState, 'active'> ({
active: !state.active,
}));
}
render(): React.ReactElement {
// ...
}
}
