Trying to grok the API of React Select by looking at its TypeScript definitions I came across this chunky state definition:
declare type StateManagedSelect = <
Option = unknown,
IsMulti extends boolean = false,
Group extends GroupBase<Option> = GroupBase<Option>
>(
props: StateManagerProps<Option, IsMulti, Group> &
RefAttributes<Select<Option, IsMulti, Group>>
) => ReactElement;
There are two things that stand out to me:
IsMulti extends boolean = false
is assigned an actual value?! What does this mean? I thought TS type generics did not allow for actual values, only default typesGroup extends GroupBase<Option> = GroupBase<Option>
. Does assigning a default type toGroup
that is identical the the thing it extend do anything? Could it not just have beenGroup extends GroupBase<Option>
, period?
CodePudding user response:
IsMulti extends boolean = false
is assigned an actual value?! What does this mean? I thought TS type generics did not allow for actual values, only default types
false
is a type (as is true
). They're literal types that are both subtypes of boolean
. From that link (you have to scroll down a bit):
There’s one more kind of literal type: boolean literals. There are only two boolean literal types, and as you might guess, they are the types
true
andfalse
. The typeboolean
itself is actually just an alias for the uniontrue | false
.
So what IsMulti extends boolean = false
is saying is that the IsMulti
type parameter expects a boolean
type argument (true
or false
), and if you don't supply it, it defaults to the type false
.
- Does assigning a default type to
Group
that is identical the the thing it extend do anything? Could it not just have beenGroup extends GroupBase<Option>
, period?
Yes, it does something: It makes it optional. If it were just Group extends GroupBase<Option>
, you'd have to supply a type argument for it when you used StateManagedSelect
. Because the type parameter has a default, you don't.
CodePudding user response:
T extends X = Y
, where Y
is a subtype of X
, simply gives a default type for T
. boolean
is equivalent to true | false
, therefore false
is a subtype of boolean
.
Here's a simplified example. Without using a default subtype:
declare function fn<T extends boolean>(arg?: T): T
let x = fn(true) // type of `x` is `true`
let y = fn(false) // type of `y` is `false`
let z = fn() // type of `z` is `boolean`
Now with the default subtype:
declare function fn<T extends boolean = false>(arg?: T): T
let x = fn(true) // same as before
let y = fn(false) // same as before
let z = fn() // type of `z` is now `false`