So my goal is to have something like this, such that the return type includes only the keys that were passed into the function:
function doTheThings<T, U = Partial<T>>(values: U): { [P in keyof U]: U[P] };
Currently, what I get instead assumes that my argument and my return types are both independent Partial<T>
, and so keys not present on the argument are available on the return type, like this:
type Thing = { name: string, age: number };
const seuss = doTheThings<Thing>({ name: 'seuss'});
// Should work, but TypeScript raises error
// Type 'string | undefined' is not assignable to type 'string'.
// Type 'undefined' is not assignable to type 'string'.
const name: string = seuss.name;
// Should work, but TypeScript raises error
// Type 'number | undefined' is not assignable to type 'undefined'.
// Type 'number' is not assignable to type 'undefined'.
const age: undefined = seuss.age;
Is what I'm trying to do even possible today in TypeScript?
The problem is how inference works with explicit and default type parameters. If you specify one type parameter, no inference will happen for the rest of the parameter (their default values will be used)
The usual workaround for this is to use function currying:
Playground Link
The function above will only return an object with the keys that were passed in. If you want to preserve the unpassed keys as well you can intersect with
Partial<T>
:Playground Link