I don't want to repeat keyof T expression in here:
// This type is meant to achieve something like ReturnType<typeof Object.entries>
type ObjectEntries<T extends object> = [keyof T, T[keyof T]][];
So I do this but it doesn't work:
type ObjectEntries<T extends object, U = keyof T> = [U, T[U]][];
// Type 'U' cannot be used to index type 'T'
However if U extends to keyof T, it works but why?
type ObjectEntries<T extends object, U extends keyof T = keyof T> = [U, T[U]][];
CodePudding user response:
U extends X means that U needs to be a type that extends X, it is also called a type constraint. If you leave it like this, U must be specified and you will get a compiler error if you don't specify it when instantiating ObjectEntries.
U = X means that if U is unspecified when instantiating ObjectEntries it will by default be X, but since U does not have any constraint, U could be any type whatsoever (for example string).
Constraints and defaults serve different purposes and so if you want U to default to keyof T so you don't have to specify it you need the = keyof T, and if you also want to constrain U so only types that are subtypes of keyof T can be specified, you will need the extends keyof T. The constraint is what gives TyepScript enough information to know that it is safe to index T with U, since any specified type for U must be a subtype of keyof T
