In below setup, I try to get the correct, inferred type for the value parameter in the onChange function. Below setup gives me a value with type string | number though I would have thought it should be string given that value is assigned a string.
import * as React from 'react'
type NumberProps = {
decimals: number;
};
type StringProps = {};
type Props<T> = {
value: T;
onChange: (value: T) => void;
} & (T extends number ? NumberProps : StringProps);
class Y<T extends string | number> extends React.Component<Props<T>> {}
new Y({ value: 2.5, onChange:((value) => { /* value is inferred as string | number, but should be number */ })})
Two things will make the inference correct - but will of course be incorrect in other ways - but might give a clue to what's wrong:
I can remove this part of the Props type: & (T extends number ? NumberProps : StringProps);
I can make Yderive from something other than React.Component, for example a class like class X<T> { constructor(props: T) {} }.
Am I doing/expecting something wrong, or is this a bug in Typescript and/or React types.
In the code you provided, the type parameter T is defined as a union of string and number, which means that the value property of the Props type can be either a string or a number. As a result, the type of the value parameter in the onChange function is also inferred as string | number.
There are a few ways you can try to get the correct inferred type for the value parameter in the onChange function. One option is to use a type guard to narrow the type of the value parameter based on the type of the value property in the Props type.
For example, you can use the typeof operator to check the type of the value property and narrow the type of the value parameter accordingly:
class Y<T extends string | number> extends React.Component<Props<T>> { onChange = (value: T) => { if (typeof this.props.value === 'number') { // value is inferred as number } else { // value is inferred as string } } }
Another option is to use a type assertion to explicitly specify the type of the value parameter. For example:
class Y<T extends string | number> extends React.Component<Props<T>> { onChange = (value: T) => {