Definitelytyped: Problema con connect() en @types/react-redux introducido en 4.4.41

Creado en 6 jun. 2017  ·  44Comentarios  ·  Fuente: DefinitelyTyped/DefinitelyTyped

Usando @types/react-redux versión 4.4.40, el siguiente código

import * as React from 'react';
import {connect} from "react-redux";

interface State {
    y: number;
}

// Own properties
interface OP {
    x: number;
}

// State properties
interface SP {
    y: number;
}

function mapStateToProps(state: State, ownProps: OP): OP & SP {
    return {
        x: ownProps.x,
        y: state.y,
    };
}

class TestComp extends React.Component<OP & SP, null> {
    render() {
        return <p>Hello</p>;
    }
}

export default connect(mapStateToProps)(TestComp);

me dejaría usar TestComp de la siguiente manera:

const tc = <TestComp x={42}/>;

Con la versión 4.4.41 y 4.4.42, lo anterior genera el siguiente error de compilación:

error TS2324: Property 'y' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<OP & SP, ComponentState>> & { children?:...'.

/cc @thasner @seansfkelley @tkqubo @blakeembrey @sandersn @mhegazy @andy-ms @hans-permana

Comentario más útil

Se rompe de nuevo en Typescript 3.0.1. ¡Hola Thien!

Todos 44 comentarios

Estoy recibiendo este error también. Parece que uno de los typedefs intercambió accidentalmente TOwnProps y TMergedProps / TStateProps , pero solo eché un vistazo superficial a index.d.ts .

¿Alguna actualización sobre este tema? Creo que puede ser un éxito para los nuevos desarrolladores que llegan a redux + mecanografiado, gracias por su gran trabajo.

@brauliodiez Fusioné el arreglo #16969 de @blakeembrey. Debería estar disponible en una hora más o menos. Avísame si te ayuda.

Creo que todavía estamos viendo este problema incluso con las correcciones de https://github.com/DefinitelyTyped/DefinitelyTyped/pull/16969. Aquí hay un componente ficticio que hice para tratar de aislar el problema:

import * as React from "react"
import { connect, MapStateToProps, MapDispatchToPropsFunction } from "react-redux"


interface RootState {
  globalA: string
  globalB: number
}

interface DumbComponentProps {
  a: string
  b: number
  c?: number
}

const DumbComponent = (props: DumbComponentProps): JSX.Element => {
  return (
    <div>Something: {props.a} {props.b} {props.c}</div>
  )
}

type ConnectedStateProps = Pick<DumbComponentProps, "a" | "b">
type ConnectedOwnProps = Pick<DumbComponentProps, "c">

const mapStateToProps: MapStateToProps<ConnectedStateProps, ConnectedOwnProps> = (
    state: RootState): ConnectedStateProps => {
  return {
    a: state.globalA,
    b: state.globalB
  }
}

const SmartComponent = connect(
  mapStateToProps
)(DumbComponent)

export default SmartComponent

Luego uso SmartComponent en algún lugar y paso c (tenga en cuenta que se supone que a & b provienen del estado).

...
return (
  <SmartComponent c{2} />
)

El error que me sale es:

error TS2322: Type '{ c: 2; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<DumbComponentProps, ComponentState>> & R...'.
  Type '{ c: 2; }' is not assignable to type 'Readonly<DumbComponentProps>'.
    Property 'a' is missing in type '{ c: 2; }'.

Al inspeccionar los tipos en VS Code, noto que está seleccionando el tipo incorrecto para SmartComponent. Cree que es React.ComponentClass<DumbComponentProps> ... pero debería ser React.ComponentClass<Pick<DumbComponentProps, "c">> (es decir, solo debería aceptar OwnProps. Esto tiene sentido por los tipos, donde ComponentDecorator es una función que devuelve ComponentClass<T> (donde T extends TOwnProps ) ... así que desafortunadamente no sé por qué no se mapea correctamente.

¿Estoy haciendo algo obviamente mal aquí? ¿Hay alguna manera de hacer que el compilador me muestre paso a paso lo que está infiriendo?

Parece que mapDistpachToProps no es opcional ahora. ¿Está bien o es un error?

Una actualización de mi comentario anterior, después de investigar un poco: he creado un caso de prueba que actualmente falla (pero creo que no debería) y una solución a los tipos que maneja mi caso, pero no maneja el caso donde tiene que adivinar cuáles son los OwnProps (por ejemplo connect()(DumbComponent) ). Mi conjunto de cambios está aquí:
https://github.com/DefinitelyTyped/DefinitelyTyped/compare/master...ritwik:react-redux/fix-ownprop-inference
Me gustaría ayudar a resolver esto, pero estoy llegando al límite de mi conocimiento con mecanografiado. Si alguien tiene ideas sobre mi caso de prueba o sugerencias, me encantaría discutirlas.

Simplemente cerrando el ciclo aquí: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/17196 parece que soluciona esto para nuestra base de código.

¿Se resolvió esto? Actualmente tengo este problema en ^5.0.8 ( IntrinsicAttributes & IntrinsicClassAttributes<Component<Pick ... ). La única diferencia es que estoy usando types en lugar de interfaces .

¿alguien? esto es un verdadero sensacional para mí desafortunadamente...

@proProbe ¿Podría proporcionar sus versiones @types/react-redux , @types/react y redux y una muestra que reproduzca el error?
También autores del paquete CC: @tkqubo @thasner @kenzierocks @clayne11 @tansongyang @nicholasboll

¡Disculpa por la respuesta tardía! Estaba trabajando con una muestra para reproducirlo. Luego, de repente me di cuenta de que esto se ha solucionado en @types/react-redux: "^5.0.8". ¡Gracias!

Todavía lo obtengo con "^ 5.0.10" :(

"@types/react": "^15.6.4",
"redux": "3.7.2",
"@types/react-redux": "^5.0.10"

Puedo compartir un fragmento de código con el autor de un paquete, pero desafortunadamente no públicamente.

La degradación a 4.4.40 como se sugirió anteriormente eliminó inmediatamente el error.

Pude resolver esto en mi propia base de código mediante la parametrización de tipos de conexión según el tipo del valor de retorno de mapStateToProps y lo que quería que fueran ownProps. Sacado de contexto si quiero llamar a mi lista de productos con una lista de ID de productos como:

<ProductList productIDs={productIDs} />

y tenga mapStateToProps para traducir esas identificaciones en productos que se mostrarán en la lista como:

const mapStateToProps = (state: RootState, ownProps: {productIDs: List<UUID>}) => {
  return { products: state.get('products').filter(
    (p: Product) => ownProps.productIDs.contains(p.uuid)) };
};

luego tuve que parametrizar connect como:

const ProductList = connect<ProductListProps, void, {productIDs: List<UUID>}>(mapStateToProps)(ProductListComponent);

Después de algunas investigaciones. Encontré una solución simple. Lo que solo tiene que hacer es tener "compilerOptions": { "strict": true } en su tsconfig.json si está conectando un componente React.Component<,>.

Typescript 2.8.x corrige esto. Actualízate y pruébalo.

Se rompe de nuevo en Typescript 3.0.1. ¡Hola Thien!

Rompiendo con TypeScript 3.2.2 también.

¿Este problema tiene alguna actualización?

Me rompió con Typescript 3.2.2 también. Sin embargo, anotar connect con connect<Props> parece solucionarlo.

Tengo el mismo problema, incluso con la anotación de conexión:/

Yo también tengo el mismo problema, ¿no hay ninguna actualización?

Rompiendo con TypeScript 3.2.4 también.

Parece que esto no se resolverá pronto.

Para todos los que tengan este problema, asegúrese de importar su componente conectado correctamente. Cambié un componente ya existente para tener una función de conexión () una vez que necesitaba acceder al estado de la aplicación desde redux. Mientras hacía esto, cambié de exportar una función sin estado a exportar mi componente de clase de forma predeterminada. Cuando no cambié la forma en que lo estaba importando en otros archivos, apareció este error.

Está funcionando.

¿Hay alguna solución para al menos silenciar este error localmente?

Definitivamente parece que hay un flip flop en algún lugar de OwnProps versus StateProps. Estoy viendo este problema en el que tenemos un componente conectado a Redux que tiene hijos.

Todo lo que hice para silenciar este problema fue usar <any> :

export default connect<any>(states, actions)(SomeComponent);

también funciona si usa componer:

export default compose<any>(
  connect(states, actions),
  withStyles(styles)
)(SomeFunctionalComponent);

Esto debería silenciar el error al pasar accesorios al componente 'inteligente'/conectado.

EDITAR: acabo de volver a leer el hilo nuevamente, y parece que la solución alternativa de @themodernlife es la mejor solución alternativa (es decir, anotar conectar o redactar usando la interfaz Props o escribir):

¿Eso no destruye también toda la verificación de tipos e Intellisense? Entonces, ¿cuál es el punto de agregar los tipos entonces? @dcefram

Sí, es una solución solo para silenciar el compilador y permitir que se compile para evitar que esto sea un "espectáculo" (o en mi caso, para evitar que vuelva a escribir todo fuera de TS o que se detenga hasta que se solucione). ). Aunque no es LA solución.

Yo también estoy esperando la solución para esto :)

Una mejor solución es escribir manualmente la llamada connect esta manera:

type StateProps = {
  // Attributes that you want mapped from redux store
}
type DispatchProps = {
  // Dispatch actions
}
type OwnProps = {
  // Other props that component expects when being created
}
type Props = StateProps & DispatchProps & OwnProps;
class ExampleComponent extends React.Component<Props> { /* ... */ }

const mapStateToProps = (state: State, ownProps: OwnProps): StateProps => { /* .. */ }
const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => { /* ... */ }

export default connect<StateProps, DispatchProps, OwnProps>
  (mapStateToProps, mapDispatchToProps)(ExampleComponent)

Esto debería crear el componente conectado correcto que espera OwnProps cuando se crea y ningún otro estado ni props de envío.

Negativo. Todavía está tratando de inferir los tipos. En su lugar, tengo que anular manualmente, escribir const y luego devolverlo como predeterminado.

const connected: React.ComponentType<OwnProps> = connect<StateProps, DispatchProps, OwnProps>(......)(Component);
export default connected;

Enfrentando el mismo problema con connect() usando "@types/react-redux": "7.0.1" y "typescript": "3.4.5" . Ninguna de las soluciones mencionadas parece haber ayudado. @TroySchmidt ¿Puede compartir cómo ha utilizado este "conectado" en el componente principal? Si es posible, un código de muestra sería muy útil.

Hola, tuve un error similar. react-redux no parece resolver el valor de retorno de mapStateToProps como "TInjectedProps", lo que provoca una exclusión incorrecta en Omit helper @types/react-redux index.d.ts:110 export type InferableComponentEnhancerWithProps .

la definición del tipo en la función de conexión resuelve el problema

// connect Redux
export const RCHeader = connect
<IHeaderStateToProps, //returned by mapStateToProps
 {}, // not necessary
 IHeaderProps, // props you want to pass through jsx/tsx
 IHeaderConnectedReduxStateProps, // combined from IHeaderMapStateToProps and IHeaderProps
 {}// not necessary
>(
    (state: ISettingsState ): IHeaderStateToProps => {
        return {
            headerLogoURL: state.settings.headerLogoURL
        }
    },
    undefined,
    undefined,
    { forwardRef: true }
)(Header);
{
  "dependencies": {
    "react": "^16.8.6",
    "react-redux": "^6.0.1",
    "redux": "^4.0.1"
  },
  "devDependencies": {
    "@types/react": "^16.8.17",
    "@types/react-redux": "^7.0.6",
    "react-scripts-ts": "^4.0.8",
    "typescript": "^3.4.5"
  }
}

¿Hay alguna actualización para esto?

Recientemente, escribo un componente que connect se reduciría. Cuando uso este componente en otro lugar, faltan todos los accesorios. Y arreglarlo por:

type StateProps = {
  /* some code */
};

type DispatchProps = {
  /* some code */
};

type OwnProps = {
  /* some code */
};

type Props = StateProps & DispatchProps & OwnProps;

const mapStateToProps = (state: IReduxState): StateProps => ({
  /* some code */
});

const mapDispatchToProps = (dispath: Dispatch<AnyAction>): DispatchProps => {
  /* some code */
};

const BaseComponent: React.FC<Props> = (props: Props) => {
  /* some code */
};

export const ConnectedComponent: React.ComponentType<OwnProps> = connect<
  StateProps,
  DispatchProps,
  OwnProps,
  IReduxState
>(
  mapStateToProps,
  mapDispatchToProps
)(BaseComponent);

Las dependencias están a continuación:

{
  "dependencies": {
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-redux": "^7.1.0",
    "redux": "^4.0.1",
  },
  "devDependencies": {
    "@types/react": "^16.8.22",
    "@types/react-dom": "^16.8.4",
    "@types/react-redux": "^7.1.0",
    "@types/redux": "^3.6.0",
    "typescript": "^3.5.2"
  }
}

agregar todos esos tipos en lugar de tener una inferencia de tipo básica no me parece una buena solución ...

Esto todavía parece un problema. Es bastante seguro que el problema se presentó en la versión 7.0.2 , ya que puedo instalar 7.0.1 y la inferencia de tipo funciona correctamente.

Funciona para mi.
@justemit publicó el enfoque correcto que funciona en las últimas versiones de reaccionar y redux.

@justemit Gracias esto me volvió loco 🙌

Editar: solucioné el problema usando React.FC<Props> 😅

Creo que este problema sigue vivo y bien en @types/react-redux@^7.1.2 :

const propTypes = {
  foo: PropTypes.number.isRequired,
  bar: PropTypes.func.isRequired
};

// inferring the Props type
interface Props extends PropTypes.InferProps<typeof propTypes> {}
// although doing it explicitly also yields the same result
interface Props {
  foo: number,
  bar: (...args: any[]) => any
}

const Foo = (props : Props) => <></> // EDIT: incorrect way to define functional components
const Foo : React.FC<Props> = (props) => <></> // EDIT: the correct way
//          ^^^^^^^^

Foo.propTypes = propTypes;
/* Foo.defaultProps = {
  foo: 1,
  bar: () => {}
} //*/

const mapStateToProps = (state : any) => ({
  foo: 1
})
const mapDispatchToProps = {
  bar: () => {}
}
const Bar = connect(mapStateToProps, mapDispatchToProps)(Foo)

const Baz = () => <Bar /> // throws an error
Type '{}' is missing the following properties from type 'Readonly<Pick<Pick<Props, never>, never> & Pick<InferProps<{ foo: Validator<number>; bar: Validator<(...args: any[]) => any>; }>, "foo" | "bar">>': foo, bar



md5-e744aa0bac3ac7f45f015259c5597ea9



El tipo 'ConnectedComponentClass<...>' no se puede asignar al tipo 'ComponentType<{}>'.
Al tipo 'Readonly<{}>' le faltan las siguientes propiedades del tipo 'Readonly; bar: Validator<(...args: any[]) => any>; }>>': foo, bar

And even if typing everything explicitly helped, I agree with <strong i="16">@alexandrudanpop</strong> that it should be possible to infer those types instead of doing everything manually 🤔 

**Edit:** for anyone looking for inspiration for a workaround, I currently resort to explicitly casting using `unknown`:
```ts
// assumes `mapDispatchToProps` is an object, could be a function if used with `ReturnType`
type OwnProps = Omit<Props, keyof ReturnType<typeof mapStateToProps> | keyof mapDispatchToProps>
connect(mapStateToProps, mapDispatchToProps)(Foo) as unknown as React.ComponentType<OwnProps>

Algo que podría ayudar con la inferencia (aún un poco de trabajo manual aunque) está haciendo algo como esto
Salir del ejemplo de @kdmadej

type StateProps = ReturnType<typeof mapStateToProps>;
type DispatchProps = typeof mapDispatchToProps;
type OwnProps = {
  a: string;
  b: number;
}

type Props = StateProps & DispatchProps & OwnProps;

const Foo = (props : Props) => <></>

const mapStateToProps = (state : any) => ({
  foo: 1
})

const mapDispatchToProps = {
  bar: () => {}
}

export default connect(mapStateToProps, mapDispatchToProps)(Foo)


// In another file
const Baz = () => <Bar /> <-- this should throw error expecting `a` and `b`

Sin embargo, el problema al que me enfrento es cuando agrego OwnProps a la mezcla. El uso <Bar /> cualquier lugar debería arrojar un error debido a la falta de accesorios a y b , pero no lo es, y realmente me está molestando (sin juego de palabras).

Lo solucioné usando esto

const ConnectedBar: React.ComponentType<OwnProps> = connect(mapStateToProps, mapDispatchToProps)(Bar);
export default ConnectedBar;

o equivalente

export default connect(mapStateToProps, mapDispatchToProps)(Foo) as React.ComponentType<OwnProps>;

Resolví mis problemas usando React.FC<Props> para escribir correctamente el componente de la función 😉
Actualicé la publicación original

¿Alguna actualización sobre esto? Como dijo @alexandrudanpop , agregar todos esos tipos en lugar de tener una inferencia de tipo básica no parece una buena solución. Estoy usando 7.2.1 y sigo teniendo el mismo problema.

En mis otros componentes tengo:

const connector = connect(mapStateToProps, mapDispatchToProps);
type PropsFromRedux = ConnectedProps<typeof connector>;
type Props = PropsFromRedux & OwnProps;

pero esto no parece funcionar si el padre también envía algunos accesorios.

También experimentando el mismo problema.
Comenzó a fallar después de la actualización de npm.
Mi solución es la siguiente:
export default connect(mapStateToProps)(ConnectedIntlProvider) as unknown as ComponentType<unknown>;
Como desconocido porque no OwnProps. Solo debería ir OwnProps.

Sin embargo, de esta manera funciona:
export default connect<StateFromProps, null, OwnProps, ApplicationState>(mapStateToProps)(viewWithIntl);

Pero de esta manera no:
export default connect<StateFromProps, DispatchFromProps, OwnProps, ApplicationState>( mapStateToProps, mapDispatchToProps, )(attachmentFormWithIntel)
Y requiere el sufijo:
as unknown as ComponentType<OwnProps>;

Utilizando
"@tipos/reaccionar": "16.9.49",
"@types/react-redux": "^7.1.9",
"mecanografiado": "^4.0.3"
"redux": "^4.0.5",
{
"dependencias": {
"reaccionar": "^16.13.1",
"reaccionar-dom": "^16.13.1",
"reaccionar-redux": "^7.2.1",
"redux": "^4.0.5",
},
"Dependencias de desarrollo": {
"@tipos/reaccionar": "16.9.49"
"@types/react-dom": "16.9.8",
"@types/react-redux": "^7.1.9",
"mecanografiado": "^4.0.3"
}
}

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

demisx picture demisx  ·  3Comentarios

victor-guoyu picture victor-guoyu  ·  3Comentarios

jgoz picture jgoz  ·  3Comentarios

jamespero picture jamespero  ·  3Comentarios

fasatrix picture fasatrix  ·  3Comentarios