diff --git a/frontend/src/metabase/components/form/FormMessage.jsx b/frontend/src/metabase/components/form/FormMessage.jsx
deleted file mode 100644
index 8b3e6c397c823218abc073f7ccafe02da7b26885..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/components/form/FormMessage.jsx
+++ /dev/null
@@ -1,57 +0,0 @@
-/* eslint-disable react/prop-types */
-import React, { Component } from "react";
-import { t } from "ttag";
-
-import { FormMessageStyled } from "./FormMessage.styled";
-
-export const SERVER_ERROR_MESSAGE = t`Server error encountered`;
-export const UNKNOWN_ERROR_MESSAGE = t`Unknown error encountered`;
-
-export default class FormMessage extends Component {
-  render() {
-    const { className, message, formSuccess, noPadding } = this.props;
-
-    const treatedMessage = getMessage(this.props);
-
-    return (
-      <FormMessageStyled
-        className={className}
-        visible={!!message}
-        noPadding={noPadding}
-        hasSucceeded={formSuccess}
-      >
-        {treatedMessage}
-      </FormMessageStyled>
-    );
-  }
-}
-
-const getMessage = ({ message, formError, formSuccess }) => {
-  if (message) {
-    return message;
-  }
-
-  if (formError) {
-    return getErrorMessage(formError);
-  }
-
-  return getSuccessMessage(formSuccess);
-};
-
-export const getErrorMessage = formError => {
-  if (formError) {
-    if (formError.data && formError.data.message) {
-      return formError.data.message;
-    } else if (formError.status >= 400) {
-      return SERVER_ERROR_MESSAGE;
-    } else {
-      return UNKNOWN_ERROR_MESSAGE;
-    }
-  }
-};
-
-export const getSuccessMessage = formSuccess => {
-  if (formSuccess && formSuccess.data.message) {
-    return formSuccess.data.message;
-  }
-};
diff --git a/frontend/src/metabase/components/form/FormMessage.styled.jsx b/frontend/src/metabase/components/form/FormMessage/FormMessage.styled.tsx
similarity index 81%
rename from frontend/src/metabase/components/form/FormMessage.styled.jsx
rename to frontend/src/metabase/components/form/FormMessage/FormMessage.styled.tsx
index d30580b09ad46518bc6956b8ddcac3d5d968b6ea..72d4d09fc8371a3049879bdde30e7a1f62f571f7 100644
--- a/frontend/src/metabase/components/form/FormMessage.styled.jsx
+++ b/frontend/src/metabase/components/form/FormMessage/FormMessage.styled.tsx
@@ -4,7 +4,11 @@ import { css } from "@emotion/react";
 import { space } from "metabase/styled-components/theme";
 import { color } from "metabase/lib/colors";
 
-export const FormMessageStyled = styled.span`
+export const FormMessageStyled = styled.span<{
+  visible?: boolean;
+  hasSucceeded?: boolean;
+  noPadding?: boolean;
+}>`
   color: ${({ hasSucceeded }) =>
     hasSucceeded ? color("success") : color("error")};
   float: left;
diff --git a/frontend/src/metabase/components/form/FormMessage/FormMessage.tsx b/frontend/src/metabase/components/form/FormMessage/FormMessage.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..8afe9e27123f59106ad892d6d9d0dac6b15ee889
--- /dev/null
+++ b/frontend/src/metabase/components/form/FormMessage/FormMessage.tsx
@@ -0,0 +1,71 @@
+import React from "react";
+import { t } from "ttag";
+
+import { FormMessageStyled } from "./FormMessage.styled";
+
+type Response = {
+  status: number;
+  data?: {
+    message?: string;
+  };
+};
+
+interface FormMessageProps {
+  className?: string;
+  message?: string;
+  noPadding?: boolean;
+  formSuccess?: Response;
+  formError?: Response;
+}
+
+const getMessage = ({
+  message,
+  formError,
+  formSuccess,
+}: Pick<FormMessageProps, "message" | "formError" | "formSuccess">) => {
+  if (message) {
+    return message;
+  }
+  if (formError) {
+    return getErrorMessage(formError);
+  }
+  return getSuccessMessage(formSuccess);
+};
+
+export const getErrorMessage = (formError?: Response) => {
+  if (formError) {
+    if (formError.data && formError.data.message) {
+      return formError.data.message;
+    } else if (formError.status >= 400) {
+      return t`Server error encountered`;
+    } else {
+      return t`Unknown error encountered`;
+    }
+  }
+};
+
+export const getSuccessMessage = (formSuccess?: Response) => {
+  return formSuccess?.data?.message;
+};
+
+function FormMessage({
+  className,
+  message,
+  formSuccess,
+  formError,
+  noPadding,
+}: FormMessageProps) {
+  const treatedMessage = getMessage({ message, formSuccess, formError });
+  return (
+    <FormMessageStyled
+      className={className}
+      visible={!!message}
+      noPadding={noPadding}
+      hasSucceeded={!!formSuccess}
+    >
+      {treatedMessage}
+    </FormMessageStyled>
+  );
+}
+
+export default FormMessage;
diff --git a/frontend/src/metabase/components/form/FormMessage/index.ts b/frontend/src/metabase/components/form/FormMessage/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..57b1abdb9364f2feba73781f8b5e405d42aa0c69
--- /dev/null
+++ b/frontend/src/metabase/components/form/FormMessage/index.ts
@@ -0,0 +1 @@
+export { default } from "./FormMessage";