I have a function called build
that constructs a User
object using the provided parameters. I want to define the function in such a way that it recognizes which parameters are being passed and incorporates them into the return value.
Initially, I thought of capturing the type of params
and utilizing it for the return type:
type User = { name: string; admin: boolean };
const build = <T extends User>(params: T): T => params
This approach works effectively since now I can use it like this:
build({ name: 'Jan', admin: true });
// the return type is: { name: string, admin: true } as intended (noting admin: true, not boolean)
However, by capturing the type with the <T extends User>
constraint, it unintentionally widens the type. Now, the following scenario is allowed without any errors:
build({ name: 'Jan', admin: true, foo: 'shouldnt be allowed' });
// the return type becomes: { name: string, admin: true, foo: string }
If I opt for a simpler approach where I don't capture the type and just return a User
, then I do get the expected behavior where passing parameters that do not exist in User
leads to an error, but the function only returns a User
without additional information from the parameters:
const build = (params: User): User => params
// Type error as expected: Object literal may only specify known
// properties, and 'foo' does not exist in type 'User'
build({ name: 'Jan', admin: true, foo: 'sdf' })
My query is whether there is a method to capture the type of params
for usage in the return type without causing the type to widen unnecessarily.