The Art of Type Arguments 9 exercises
solution

Constrain to the Array Member, Not the Array

The solution is kind of tricky to find, so let's take it step-by-step.

Here's what the starting point was:

const makeStatus = <TStatuses extends string[]>(statuses: TStatuses) => {
  return statuses;
};

Inside of the generic slot, makeStatus is being passed in an array of stri

Loading solution

Transcript

0:00 We've got this set up so that, TStatuses extends string array, we've still got our issue. The solution here is a tricky one to find. What's going on here is that, inside the generic slot, the thing that's being passed into makeStatus is an array of strings.

0:20 Even though it looks like it should be inferred deeper, it's not being inferred deeper. We're not inferring the members of that array. When you have an object like this, because an array is an object, basically, then TypeScript is not going to infer its members unless you point its focus there.

0:43 We know that the principle that we've had before is that it's often better to go lower. If you have a choice between representing the higher object or the members of that object, you should probably represent the members of that object, if that's all you care about. In this case, that is all we care about.

0:58 What happens if, instead of TStatuses, we represent it as TStatus? Now, what's happening is that the thing that's being inferred is the thing inside the generic slots, so we end up with info or debug or error or warning instead of just string.

1:17 I don't know why this works. There's probably some bit in the compiler that's saying, "OK. If it's representing this, then go deeper in." We can even just remove this, I think. If we remove this, then it just goes into string here. There's something in the compiler that is telling it to, "When you have an extend string here and when it's in a member of an array, then infer those members literally."

1:46 There is some stuff coming in 5. that will make this easier, but I will cover that in a different section. What this proves is that the rule of thumb of, "When you have a choice, go lower. Don't choose the high representation. Choose the lowest, tightest representation," in general leads you to some good results.

2:05 Also, constraining this to be only the things that we care about is also important for getting this good inference.