Why doesn't TypeScript properly type Object.keys?
At Notion, we re-type Object.keys and Object.entries for the situations where you want more specific key types. For example, iterating over a `Record&lt;ThingyIdType, ThingyUpdate&gt;` while preserving the well-typed ID key, or iterating over a `SchemaDefinition&lt;Thingy&gt;` which is known to be statically declared as an exact object.<p><pre><code>    &#x2F;**
     * Like Object.keys, but unsound in exchange for more convenience.
     *
     * Casts the result of Object.keys to the known keys of an object type,
     * even though JavaScript objects may contain additional keys.
     *
     * Only use this function when you know&#x2F;control the provenance of the object
     * you&#x27;re iterating, and can verify it contains exactly the keys declared
     * to the type system.
     *
     * Example:
     * ```
     * const o = {x: &quot;ok&quot;, y: 10}
     * o[&quot;z&quot;] = &quot;UNTRACKED_KEY&quot;
     * const safeKeys = Object.keys(o)
     * const unsafeKeys = objectKeys(o)
     * ```
     * =&gt; const safeKeys: string[]
     * =&gt; const unsafeKeys: (&quot;x&quot; | &quot;y&quot;)[] &#x2F;&#x2F; Missing &quot;z&quot;
     *&#x2F;
    export const objectKeys = Object.keys as &lt;T&gt;(obj: T) =&gt; Array&lt;keyof T&gt;
    
    
    &#x2F;**
     * The type of a single item in `Object.entries&lt;T&gt;(value: T)`.
     *
     * Example:
     * ```
     * interface T {x: string; y: number}
     * type T2 = ObjectEntry&lt;T&gt;
     * ```
     * =&gt; type T2 = [&quot;x&quot;, string] | [&quot;y&quot;, number]
     *&#x2F;
    export type ObjectEntry&lt;T&gt; = {
     &#x2F;&#x2F; Without Exclude&lt;keyof T, undefined&gt;, this type produces `ExpectedEntries | undefined`
     &#x2F;&#x2F; if T has any optional keys.
     [K in Exclude&lt;keyof T, undefined&gt;]: [K, T[K]]
    }[Exclude&lt;keyof T, undefined&gt;]
    
    &#x2F;**
     * Like Object.entries, but returns a more specific type which can be less safe.
     *
     * Example:
     * ```
     * const o = {x: &quot;ok&quot;, y: 10}
     * const unsafeEntries = Object.entries(o)
     * const safeEntries = objectEntries(o)
     * ```
     * =&gt; const unsafeEntries: [string, string | number][]
     * =&gt; const safeEntries: ObjectEntry&lt;{
     *   x: string;
     *   y: number;
     * }&gt;[]
     *
     * See `ObjectEntry` above.
     *
     * Note that Object.entries collapses all possible values into a single union
     * while objectEntries results in a union of 2-tuples.
     *&#x2F;
    export const objectEntries = Object.entries as &lt;T&gt;(
     o: T
    ) =&gt; Array&lt;ObjectEntry&lt;T&gt;&gt;</code></pre>