Skip to content

React onChange handler with function union argument causes onChange to show the wrong typeΒ #50127

@wbolduc

Description

@wbolduc

Bug Report

The onChange in the given example seems to change types when you pass a function that also accepts a function
the handler

TS playground

πŸ”Ž Search Terms

React, onChange

⏯ Playground Link

TS playground

πŸ’» Code

import React, { useState } from 'react'


interface Test<Emp extends null | number> {
	empty_value?: Emp;
	value: number | null;
	onChange: (value: number | Emp) => void;
}

//types stolen from react's index.d.ts
type SetStateAction<S> = S | ((prevState: S) => S);
type Dispatch<A> = (value: A) => void;

const Aaaa = <E extends number | null = null>({
	value,
	// @ts-ignore-next-line This will be null unless the user passes a number in which case this is overridden anyways
	empty_value = null,
	onChange,
}: Test<E>) => (
	<input
		type="number"
		value={value ?? ""}
		onChange={(e) =>
			onChange(e.target.value === "" ? empty_value : +e.target.value)
		}
	/>
);

const B = () => {
	const [value, setValue] = useState(1);

	const handleChange: Dispatch<SetStateAction<number>> = (value) =>
		setValue(value);
	
	const handleChange2: Dispatch<number> = (value) => setValue(value)

	return (
		<>
			<Aaaa value={value} onChange={setValue} empty_value={0} />
			<Aaaa value={value} onChange={handleChange} empty_value={0} />
			{/* If you hover over the onChange in the above two components it suggests that suddenly onChange could also recieve a null value */}

			{/* If you hover over the onChange of the following components, the onChange type appears as expected */}
			<Aaaa value={value} onChange={handleChange2} empty_value={0} />
			<Aaaa value={value} onChange={(v) => setValue(v)} empty_value={0} />
		</>
	);
};

πŸ™ Actual behavior

onChange does not accept handers and displays as possibly being called with null

πŸ™‚ Expected behavior

all onChanges in the ts playground should not produce errors

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions