Microsoft/TypeScript

Spread operator in JSX causes loss of type information for inline functions defined outside the spread operator

Open

#54 841 ouverte le 30 juin 2023

Voir sur GitHub
 (3 commentaires) (0 réactions) (0 assignés)TypeScript (6 726 forks)batch import
BugDomain: JSX/TSXHelp Wanted

Métriques du dépôt

Stars
 (48 455 stars)
Métriques de merge PR
 (Merge moyen 6j 17h) (9 PRs mergées en 30 j)

Description

Bug Report

When defining conditional types on a JSX component, using a spread operator causes loss of type information on inline functions while removing the spread operator resolves the issue.

🔎 Search Terms

  • "jsx spread"
  • "TS7006"

⏯ Playground Link

Playground link with relevant code

💻 Code

Given the following types and JSX:

/**
 * Either all properties are included, or none of them should be
 * @example
 * type Ex = AllOrNone<{ search: string; onSearchChange: (value: string) => void}>
 *
 * // Ok
 * const t1: Ex = {
 *   search: "hello",
 *   onSearchChange: (value) => console.log(value)
 * }
 *
 * // Error, needs onSearchChange
 * const t2: Ex = {
 *   search: "hello",
 * }
 *
 * // Error, needs search
 * const t3: Ex = {
 *   onSearchChange: (value) => console.log(value)
 * }
 */
export type AllOrNone<T> = T | { [K in keyof T]?: never };


export type OrderHistoryTableProps = {
  data: OrderRow[];
  noDataText?: string;
} & SortParams &
  FilterParams &
  SearchParams;

type SortParams = AllOrNone<{
  sorting: SortingState;
  onSortChange: (state: SortingState) => void;
}>;

type FilterParams = AllOrNone<{
  filter: ColumnFiltersState;
  onFilterChange: (state: ColumnFiltersState) => void;
}>;

type SearchParams = AllOrNone<{
  search: string;
  onSearchChange: (value: string) => void;
}>;

function OrderHistoryTable({
  data,
  noDataText = "No orders to display!",
  onFilterChange,
  onSortChange,
  sorting,
  filter,
  search,
  onSearchChange,
}: OrderHistoryTableProps): JSX.Element {
  ...
}

/* sorting, filter, and search are correct types */
<OrderHistoryTable
  data={rowData}
  {...{ sorting, filter, search }}
  onSortChange={onSortChange}
  onFilterChange={setFilter}
  onSearchChange={(value) => setSearch(value)} // TS7006: Parameter 'value' implicitly has an 'any' type.
/>

However, removing the spread operator resolves the issue:

<OrderHistoryTable
  data={rowData}
  sorting={sorting}
  filter={filter}
  search={search}
  onSortChange={onSortChange}
  onFilterChange={setFilter}
  onSearchChange={(value) => setSearch(value)}
/>

🙁 Actual behavior

While using the spread operator for other props, the inline function loses type information.

🙂 Expected behavior

Given that the values provided in the spread operator are the correct type, the arguments in the inline function should retain type information.

Guide contributeur