I'm trying to create a generic type to define a common function shape (express handler). Here I've simplified this to get to the core of my issue:
So I've created a type to represent the common function shape:
type Builder = () => BuilderReturn;
type BuilderReturn = {
prop1: string;
}
This means that a variable that is given this type must be assigned a function with no args that returns an object with one property, prop1
, a string
. However, when I use this function type
in practice, while TypeScript does ensure prop1 is present and a string, it doesn't restrict the return type, meaning I can add arbitrary properties to the return object without TypeScript complaining:
const myBuilder: Builder = () => ({
prop1: 'something',
junk: true, // TypeScript doesn't care if this is here
});
My expectation would be that by specifying an object shape as a return type for the Builder
type, this would ensure the return type matches the object shape, no exceptions.
Now, if I explicitly define the return type in my function definition (i.e., not relying on the return type checking implied in the Builder
type), it does correctly flag junk
as not being a member of BuilderReturn
.
const myBuilder: Builder = (): BuilderReturn => ({
prop1: 'something',
junk: true, // TypeScript now identifies this as a problem
});
But this isn't ideal because I don't want consumers of this utility type to need to know that they have to specify both Builder
and BuilderReturn
each time a new builder function is defined.
Maybe I have an inherent misunderstanding about using a type defined as a function in a function expression that expects very explicit inputs and outputs.
If anyone could cast some light on how to achieve this with a single type as a part of a function expression, it would be much appreciated!