Búsqueda de sitios web

Error de Typescript: no se puede asignar al acceder a tipos de xState


Hola a todos, estoy teniendo un pequeño problema de escritura con un componente que estoy tratando de arreglar:

interface ChildrenProps {
  exit: (force?: boolean) => void;
  state: StateValue;
}
interface Props {
  // https://reactjs.org/docs/render-props.html
  children: (childrenProps: ChildrenProps) => {};
  close: () => void;
  isOpen: boolean;
  state: StateValue;
}
const ModalDialog: React.FC<Props> = function (props) {
  const { children, close, isOpen } = props;
  const layers = useContext(LayersContext);
  const [state, send] = useMachine(modelDialogMachine, {
    actions: {
      close,
    },
  });
  ...
  const childrenProps = { state: state.value, exit: sendExitEvent };

  return ReactDOM.createPortal(
    <ModalDialogContext.Provider value={contextValue}>
      <Backdrop className={state.value} onClick={handleBackdropClick}>
        <Dialog onClick={handleDialogClick}>{children(childrenProps)}</Dialog>
      </Backdrop>
    </ModalDialogContext.Provider>,
    container,
  );
};

En <Backdrop className={state.value} onClick={handleBackdropClick}> estoy obteniendo:

 Type 'StateValue' is not assignable to type 'string | undefined'.
      Type 'StateValueMap' is not assignable to type 'string'.
  Overload 2 of 2, '(props: StyledComponentPropsWithAs<"div", DefaultTheme, {}, never>): ReactElement<StyledComponentPropsWithAs<"div", DefaultTheme, {}, never>, string | ... 1

Donde StateValue son tipos de import { StateValue } from 'xstate', la biblioteca de máquinas de estado xstate.

El nombre de la clase se usa para cambiar entre estilos:

export const Backdrop = styled.div`
  &.entering {
  ...

¿Cómo puedo resolver este error de tipeo? Hola a todos, estoy teniendo un pequeño problema de tipeo con un componente que estoy tratando de arreglar:

interface ChildrenProps {
  exit: (force?: boolean) => void;
  state: StateValue;
}
interface Props {
  // https://reactjs.org/docs/render-props.html
  children: (childrenProps: ChildrenProps) => {};
  close: () => void;
  isOpen: boolean;
  state: StateValue;
}
const ModalDialog: React.FC<Props> = function (props) {
  const { children, close, isOpen } = props;
  const layers = useContext(LayersContext);
  const [state, send] = useMachine(modelDialogMachine, {
    actions: {
      close,
    },
  });
  ...
  const childrenProps = { state: state.value, exit: sendExitEvent };

  return ReactDOM.createPortal(
    <ModalDialogContext.Provider value={contextValue}>
      <Backdrop className={state.value} onClick={handleBackdropClick}>
        <Dialog onClick={handleDialogClick}>{children(childrenProps)}</Dialog>
      </Backdrop>
    </ModalDialogContext.Provider>,
    container,
  );
};

En <Backdrop className={state.value} onClick={handleBackdropClick}> estoy obteniendo:

No overload matches this call.
  Overload 1 of 2, '(props: Pick<Pick<Pick<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "slot" | "style" | ... 252 more ... | "onTransitionEndCapture"> & { ...; }, "ref" | ... 254 more ... | "onTransitionEndCapture"> & Partial<...>, "ref" | ... 254 more ... | "onTransitionEndCapture"> & { ...; } & { ...; }): ReactElement<...>', gave the following error.
    Type 'StateValue' is not assignable to type 'string | undefined'.
      Type 'StateValueMap' is not assignable to type 'string'.
  Overload 2 of 2, '(props: StyledComponentPropsWithAs<"div", DefaultTheme, {}, never>): ReactElement<StyledComponentPropsWithAs<"div", DefaultTheme, {}, never>, string | ... 1 more ... | (new (props: any) => Component<...>)>', gave the following error.

Donde StateValue son tipos de import { StateValue } from 'xstate', la biblioteca de máquinas de estado xstate.

El nombre de la clase se usa para cambiar entre estilos:

export const Backdrop = styled.div`
  &.entering {
  ...

Si hago console.log de state.value, obtengo cadenas:

ModalDialog.js:79 exited
ModalDialog.js:79 entering
ModalDialog.js:79 entered

Escribiendo para StateValue y StateValueMap

export declare type StateValue = string | StateValueMap;

export interface StateValueMap {
    [key: string]: StateValue;
}

¿Cómo puedo resolver este error de tipeo?

Respuesta #1

Si sabes que será una cadena, puedes hacer un casteo de tipo: className={state.value as string}. Solo ten en cuenta que máquinas más complejas pueden devolver un objeto (es decir, si tienes una máquina paralela), por lo que el cast solo es válido si no planeas necesitar nunca la variante StateValueMap. Si lo haces, podrías encontrarte con el error Objects are not valid as a React child en tiempo de ejecución si, por ejemplo, hiciste <p>{state.value}</p>.