>And the purpose of a good database schema (or typeful design) is to make nonsensical things impossible, even in principle.
Can you elaborate on what is the nonsensical thing possible with two tables of the same type?
To me the (A UNION B) example makes very much sense exactly in the case that you want all x s.t. (x is in A) OR (x is in B). With differently named id columns you might have to write this as (excuse my pseudo code):
(RENAME(A, a_id TO a_or_b_id) UNION RENAME(B, b_id TO a_or_b_id))
which is indeed more explicit. Having written that I might see the rub here. In the article the column "item_id" is kind of a "view_or_download_id" and which it is is only specified the namespace (i.e. the name of the table ITEMS or DOWNLOADS the tuple belongs to). In an OO world this would be the difference between:
class Person { public string Name { get; set; } }
...
var employees = new List<Person>(...);
var managers = new List<Person>(...);
and the version where employee and manager types are incompatible:
class Person { public string Name { get; set; } }
class Employee : Person {}
class Manager : Person {}
...
var employees = new List<Employee>(...);
var managers = new List<Manager>(...);
The latter would indeed prevent e.g. employees.Concat(managers) on accident. However, in many programming scenarios the former would be preferred for the increased code reusability. Is this not an objective in database design (with e.g. stored procedures that could be applied to more than one set of tables)?