Avoid usage of type any, really

Matthias Falk
2 min readJan 14, 2021

This is only a side remark that has nothing to do with your algorithmic ideas. You defined

type BuildTuple<L extends number, T extends any[] = []> =T extends { length: L }? T: BuildTuple<L, [...T, any]>;

I strongly recommend to replace any by unknown . I have just learned the lesson that I describe here by myself. I had read before this article but it didn’t mention the, to my mind, most important counterargument against the usage of any: Besides it being a top type (as to be expected) it is also a bottom type and that came as a big surprise to me. I stumbled over it in connection with your EQ type

type EQ<A, B> =A extends B? (B extends A ? true : false): false;

First of all this should be changed to

type EQ<A, B> =
[A] extends [B]
? ([B] extends [A] ? true : false)
: false;

to prevent unintended distribution as I have argued for in my previous comment “Your EQ type looks innocent but is really insidious” (I don’t know how to link it here). As for the anyproblem, have a look at this

const test: EQ<boolean, any> = true;  // !!!

What? boolean and any are equivalent? The reason is that

const testAnyExtends: (any extends boolean ? true : false) = true;

any is simultaneously a bottom type, thus extending anything, exactly as the “official” bottom type never does. I understand now why Microsoft implemented it this way, viz. for to use any as a vehicle to switch type checking off. Nevertheless, I was completely unaware of this consequence and I guess, I am not the only one. The lesson I took is: Use unknown instead of any since the former is just a top not simultaneously a bottom type. The difference is demonstrated as well here

let testAny: any = 'hello';
let testUnknown: unknown = 'hello';
let x: number;
x = testAny; // !!! this assignment is admissible !!!
x = testUnknown; // this induces a compiler error as it should be

After changing any to unknown in my arithmetic implementation (see my subsequent comment that will follow) some cases of evaluating to wrong branches in conditional types within my type CheckedNaturalNumber vanished. Thus, it is not just an academic problem. It had real consequences in my code. So, I recommend to change your BuildTuple type into

type BuildTuple<L extends number, T extends unknown[] = []> =T extends { length: L }? T: BuildTuple<L, [...T, unknown]>;

--

--

No responses yet