Home > Blockchain >  What does a generic type that `extends boolean = false` mean?
What does a generic type that `extends boolean = false` mean?

Time:03-29

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:

  1. 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
  2. Group extends GroupBase<Option> = GroupBase<Option>. Does assigning a default type to Group that is identical the the thing it extend do anything? Could it not just have been Group extends GroupBase<Option>, period?

CodePudding user response:

  1. 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 and false. The type boolean itself is actually just an alias for the union true | 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.

  1. Does assigning a default type to Group that is identical the the thing it extend do anything? Could it not just have been Group 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`
  • Related