Repository: apache/airflow
File: airflow-core/src/airflow/ui/src/pages/Jobs.tsx (TypeScript)

Code before:
import { ErrorAlert } from "src/components/ErrorAlert";
import { FilterBar } from "src/components/FilterBar";
import { StateBadge } from "src/components/StateBadge";
import Time from "src/components/Time";
import { SearchParamsKeys } from "src/constants/searchParams";
import { useFiltersHandler, type FilterableSearchParamsKeys } from "src/utils";

const createColumns = (translate: TFunction): Array<ColumnDef<JobResponse>> => [
  {
    accessorKey: "id",
    header: translate("jobs.columns.id"),
  },
  {
    accessorKey: "job_type",
    header: translate("jobs.columns.jobType"),
  },
  {
    accessorKey: "state",
    cell: ({
      row: {
        original: { state },
      },
    }) =>
      state === null ? (
        ""
      ) : (
        <StateBadge state={state as TaskInstanceState}>{translate(`common:states.${state}`)}</StateBadge>
      ),
    header: translate("common:state"),
  },
  {
    accessorKey: "hostname",
    header: translate("jobs.columns.hostname"),
  },
  {
    accessorKey: "start_date",
    cell: ({ row: { original } }) => <Time datetime={original.start_date} />,
    header: translate("common:startDate"),
  },
  {
    accessorKey: "end_date",
    cell: ({ row: { original } }) => <Time datetime={original.end_date} />,
    header: translate("common:endDate"),
  },
  {
    accessorKey: "latest_heartbeat",
    cell: ({ row: { original } }) => <Time datetime={original.latest_heartbeat} />,
    header: translate("jobs.columns.latestHeartbeat"),
  },
  {
    accessorKey: "executor_class",

Review comment (suggestion):
`state` here is typed as `string | null` on `JobResponse`, but it's cast to TaskInstanceState. Job states are a subset of `TaskInstanceState`, but the cast is kind of semantically misleading. Maybe Consider adding a `JobState` type or add a comment noting the cast is intentional.

Code after:
import { ErrorAlert } from "src/components/ErrorAlert";
import { FilterBar } from "src/components/FilterBar";
import { StateBadge } from "src/components/StateBadge";
import Time from "src/components/Time";
import { SearchParamsKeys } from "src/constants/searchParams";
import { useFiltersHandler, type FilterableSearchParamsKeys } from "src/utils";

const createColumns = (translate: TFunction): Array<ColumnDef<JobResponse>> => [
  {
    accessorKey: "id",
    header: translate("jobs.columns.id"),
  },
  {
    accessorKey: "job_type",
    header: translate("jobs.columns.jobType"),
  },
  {
    accessorKey: "state",
    cell: ({
      row: {
        original: { state },
      },
    }) =>
      // Job states (running, success, failed, restarting) are a subset of TaskInstanceState
      state === null ? undefined : (
        <StateBadge state={state as TaskInstanceState}>{translate(`common:states.${state}`)}</StateBadge>
      ),
    header: translate("common:state"),
  },
  {
    accessorKey: "hostname",
    header: translate("jobs.columns.hostname"),
  },
  {
    accessorKey: "start_date",
    cell: ({ row: { original } }) => <Time datetime={original.start_date} />,
    header: translate("common:startDate"),
  },
  {
    accessorKey: "end_date",
    cell: ({ row: { original } }) => <Time datetime={original.end_date} />,
    header: translate("common:endDate"),
  },
  {
    accessorKey: "latest_heartbeat",
    cell: ({ row: { original } }) => <Time datetime={original.latest_heartbeat} />,
    header: translate("jobs.columns.latestHeartbeat"),
  },
  {
    accessorKey: "executor_class",
    header: translate("jobs.columns.executorClass"),