What difference between these two functions? Both work the same. I know how extends work in interfaces but I can't understand the differences here
const func = <T extends string>(str: T): T => str
const func = <T = string>(str: T): T => str
CodePudding user response:
These are very different things.
<T extends string>
This is a constraint. This means that T
must be string
or a subtype of string
(i.e. a string literal)
const func = <T extends string>(str: T): T => str
func("A") // returns type "A" because "A" is a subtype of string
func<string>("A") // returns type string because the inference was overridden
func(123) // error 123 is not a subtype of string
<T = string>
This is a default type. In this case T
is not constrained, but if omitted string
is used as the type of T
.
const func = <T = string>(str: T): T => str
func("A") // returns type "A" because "A" is a inferred for T
func<string>("A") // returns type string because the inference was overridden
func(123) // returns type 123 because 123 is inferred as the type for T
The default type doesn't make a lot of sense in this example though since it is inferred by the argument when you omit it. So lets look at a different example:
type MyType<T = string> = { value: T }
type TestA = MyType<number> // equivalent to { value: number }
type TestB = MyType // equivalent to { value: string }
Note how in TestB
you can leave out the generic, and the default of string
is used instead.
However, in the case of T extends string
both TestA
and TestB
are type errors:
type MyType<T extends string> = { value: T }
type TestA = MyType<number> // type error: number does not extend string
type TestB = MyType // type error: missing generic parameter