I have searched a lot and read several question to find a solution to my problem but in no vain. Can you help me?!
What I don’t understand is that when a type extends boolean
and put in the if statement condition it should be narrowed to true
but TypeScript has a different idea in some situation:
import Select from "react-select";
export interface Option<Value> {
readonly value: Value;
readonly label?: string;
readonly isDisabled?: boolean;
readonly isFixed?: boolean;
}
export type PropValue<Value, IsMulti extends boolean> = IsMulti extends true
? Value[]
: Value;
const ComboBox = <Value, IsMulti extends boolean>(props: {
value?: PropValue<Value, IsMulti>;
options: Option<Value>[];
isMulti: IsMulti;
}) => {
const { value, isMulti, options } = props;
const mapValue = (x?: PropValue<Value, IsMulti>) => {
if (!x) return undefined;
if (isMulti) {
isMulti;
// ??? why isMulti is not of type `true` but rather still `extends boolean`
// ??? x should be an array but doesn't seem to be narrowed as well
return options.filter(({ value }) => x.includes(value));
}
};
return <Select value={mapValue(value)} isMulti={isMulti} />;
};
A more simple scenario will work as expected:
function experimenting<T extends boolean>(x: boolean, y: T) {
if (x) {
x; //: true
}
if (y) {
y; //: true
}
}
- Can you explain
isMulti
in the first scenario didn’t get narrowed to justtrue
? - How to fix the code above so that both
isMulti
andx
are narrowed.
2
Answers
T extends boolean
doesn’t mean thatT
is equal toboolean
. The extends clause just means thatT
is a subset of theboolean
and the compiler isn’t able to narrow the type to justtrue
since it doesn’t know the exact type of it.Example:
never
is an empty set and the subsets of theboolean
aretrue
|false
|never
, since an empty set is also a subset. Thus, we can passnever
to the function that expects a generic parameter that extendsboolean
:You can instead of extending
Boolean
, extendtrue | undefined
on theComboBox
andPropValue
, and a default typeundefined
so that you don’t have to passisMulti={undefined}
And in the
PropValue
you can narrow it down usingNonNullable
to check if it’strue
Also, a union for props would work