Function getInheritedPropertyKeys

get all inherited list of keys (string keys and symbol keys) of an object, up till a certain depth.

directly owned keys will not be returned. for that, you should use the getOwnPropertyKeys function.

the optional depth parameter lets you control how deep you'd like to go collecting the inherited keys.

Object.prototype

import { assertEquals } from "jsr:@std/assert"

const
symbol_h = Symbol("symbol h"),
symbol_i = Symbol("symbol i"),
symbol_j = Symbol("symbol j")

class A {
a = { v: 1 }
b = { v: 2 }
c: { v: number }
d() { return { v: 4 } }
e() { return { v: 5 } }
f = () => { return { v: 6 } }
g: () => ({ v: number })
[symbol_h]() { return { v: 8 } }
[symbol_i] = () => { return { v: 9 } }

constructor() {
this.c = { v: 3 }
this.g = () => { return { v: 7 } }
}
}

class B extends A {
override a = { v: 11 }
override e() { return { v: 15 } }
//@ts-ignore: typescript does not permit defining a method over the name of an existing property
override g() { return { v: 17 } }
[symbol_j] = () => { return { v: 20 } }

constructor() { super() }
}

const
a = new A(),
b = new B()

assertEquals(
new Set(getInheritedPropertyKeys(a)),
new Set(["constructor", "d", "e", symbol_h]),
)

// below, notice how the inherited keys of `a` equal to its prototype's owned keys.
// this is because methods of instances of `A` are defined on the prototype (i.e. properties of the prototype, rather than the instances').
assertEquals(
new Set(getInheritedPropertyKeys(a)),
new Set(getOwnPropertyKeys(A.prototype)),
)

// also notice that inherited keys of `A.prototype` comes out as empty here,
// even though it does techinally inherit members from its own prototype (which is `Object.prototype`).
// the reason is that by default, we do not go deeper than `Object.prototype` to look for more keys.
// this is because from an end-user's perspective, those keys are not useful.
assertEquals(
getInheritedPropertyKeys(A.prototype),
[],
)

assertEquals(
new Set(getInheritedPropertyKeys(b)),
new Set(["constructor", "e", "g", "d", symbol_h]),
)
assertEquals(
new Set(getInheritedPropertyKeys(b)),
new Set([
...getOwnPropertyKeys(B.prototype),
...getInheritedPropertyKeys(B.prototype),
]),
)
assertEquals(
new Set(getInheritedPropertyKeys(B.prototype)),
new Set(["constructor", "e", "d", symbol_h]),
)

// testing out various depth
assertEquals(
new Set(getInheritedPropertyKeys(a, 1)),
new Set(getOwnPropertyKeys(A.prototype)),
)
assertEquals(
new Set(getInheritedPropertyKeys(b, 1)),
new Set(getOwnPropertyKeys(B.prototype)),
)
assertEquals(
new Set(getInheritedPropertyKeys(b, A.prototype)),
new Set(getOwnPropertyKeys(B.prototype)),
)
assertEquals(
new Set(getInheritedPropertyKeys(b, 2)),
new Set([
...getOwnPropertyKeys(B.prototype),
...getOwnPropertyKeys(A.prototype),
]),
)
// below, we collect all inherited keys of `b`, including those that come from `Object.prototype`,
// which is the base ancestral prototype of all objects.
// to do that, we set the `depth` to `null`, which is the prototype of `Object.prototype`.
// the test below may fail in new versions of javascript, where
assertEquals(
new Set(getInheritedPropertyKeys(b, null)),
new Set([
"constructor", "e", "g", "d", symbol_h,
"__defineGetter__", "__defineSetter__", "hasOwnProperty", "__lookupGetter__", "__lookupSetter__",
"isPrototypeOf", "propertyIsEnumerable", "toString", "valueOf", "toLocaleString",
]),
)
  • Type Parameters

    • T extends object

    Parameters

    • obj: T

      the object whose inherited keys are to be listed.

    • depth: null | number | Object = ...

      the inheritance depth until which the function will accumulate keys for.

      • if an object A is provided as the depth, then all inherited keys up until A is reached in the inheritance chain will be collected, but not including the keys of A.
      • if a number N is provided as the depth, then the function will collect keys from N number of prototypes up the inheritance chain.
        • a depth of 0 would imply no traversal.
        • a depth of 1 would only traverse the first direct prototype of obj (i.e. getOwnPropertyKeys(Object.getPrototypeOf(obj))).

    Returns (keyof T)[]

    an array of keys that the object has inherited (string or symbolic keys).