Pasar un componente con props arbitrarios/genéricos a la función connect de react-redux en TypeScript
Estoy intentando conectar un elemento de React con react-redux que tiene props arbitrarias/genéricas, pero no se está compilando correctamente. He intentado usar JSXElementConstructor y (new (props: Props) => React.Component<Props, any>) en lugar de ComponentType, pero obtuve un error diferente sobre cómo Props podría instanciarse con un tipo diferente. Aquí está el código. Cualquier ayuda sería apreciada.
https://github.com/piotrwitek/react-redux-typescript-guide/issues/55 parece relacionado, pero eso parece ser sobre que las props tienen un genérico, en lugar de que las props mismas sean un genérico.
Código
import React from "react";
import { connect } from "react-redux";
interface StoreState {
someState: number;
}
// Tried `React.JSXElementConstructor<Pros>`
// and `(new (props: Props) => React.Component<Props, any>)`
// instead of `React.ComponentType<Props>`, but got a different error.
function createWrapperComponent<Props>(
componentElement: React.ReactElement<
Props,
React.ComponentType<Props> & { update(props: Props): void }
>
) {
const props = componentElement.props;
const UnconnectedComponent = componentElement.type;
const ConnectedComponent = connect<StoreState, {}, Props, StoreState>(
(state) => state
)(UnconnectedComponent);
return class WrapperComponent extends React.Component<any> {
static update = UnconnectedComponent.update;
render() {
return <ConnectedComponent {...props} />;
}
};
}
Enlace al patio de juegos: Proporcionado
Respuesta #1
Actualización: Aquí hay un enfoque que evita la conversión inicial a any. Ahora estoy convirtiendo las props pasadas a ConnectedComponent en su lugar. Investigar el problema de tipo allí podría revelar si hay más problemas potenciales además del que mencioné.
Lo que estás haciendo no es correcto. Si Props fueran { someState: string }, tu UnconnectedComponent estaría esperando que su prop someState fuera un string, pero sería un number.
Si stateProps y dispatchProps deben sobrescribir ownProps, que es lo que tu código está haciendo ahora, no estoy seguro de si vas a poder hacer que los tipos funcionen automáticamente de la manera que deseas. TypeScript no puede determinar que lo siguiente es válido:
function a<Props>(
b: { [K in keyof Props]: K extends keyof StoreState ? StoreState[K] : Props[K] }
): Omit<Props, keyof StoreState>
{
return b;
}
Tal vez deberías morder la bala y usar any. Aquí tienes un ejemplo de cómo podrías intentar hacer que los tipos visibles para el llamador sean más seguros.
Si en cambio quieres que ownProps sobrescriba stateProps, querrías proporcionar un argumento mergeProps a connect.
Sin embargo, ten en cuenta que cuando creas un ReactElement a través de JSX, el campo type tiene tipo any, lo cual, por supuesto, no te dará seguridad de tipos si luego llamas a createComponent.
Respuesta #2
Tus Props no se refieren a ningún tipo definido. Entonces supongo que dejarlo en blanco está bien?
function createComponent(componentElement: React.ReactElement<{}, React.ComponentType>) {
const props = componentElement.props;
const UnconnectedComponent = componentElement.type;
const ConnectedComponent = connect<StoreState, {}, {}, StoreState>(state => state)(UnconnectedComponent);
return <ConnectedComponent {...props} />
}
