interface in TypeScript can be thought of the shape of arguments that
a function needs in order to work. Often these are written by hand, and
sometimes there might be tooling that generates the type definitions (
file, for instance) based off on a JSON spec.
Most of our backend systems at work are written in Java, which expose API specs for every API endpoint the UI consumes. We use a such a tool to generate the corresponding TypeScript definition files based off of these. A function that then directly uses these response types for its arguments, but one which may not use all the parameters, becomes harder to reuse.
Consider a type definition for the
422 Unprocessable Entity error response of GitHub’s v3 API. Consider this definition is auto-generated. Also consider that in the first version, the
400 Bad Request error response wasn’t yet defined. It may look something like the following:
message. If we directly used the types from this structure in their entirety, it could look something like this:
This works very well…until we have to add handling for a
400 Bad Request
error type. The new interface won’t have an
errors array type, so the
renderErrorMessage can’t be directly reused; it strictly
expects the maximal type of
Error422 with the
errors property set to an array. This is despite of the fact that
technically we know it works with the new object.
Although this looks like a trivial example, I’ve seen many such instances in our code-base, which has grown organically over the years with multiple contributors changing different portions of the app. In many cases, the programmer would jump through hoops getting the “generic” function to work with multiple of these complex interfaces.
A much better design in such cases, and for the
renderErrorMessage function here, would be something like the following:
As a thumb-rule it’s always a good practice to make the interface of the function take the minimal set of attributes and resist the temptation to use the mechanically-derived interfaces directly. Sounds obvious enough in retrospect!