The object
type (noting the lowercase o
) was specifically created to encompass "non-primitive" types; in essence, object
is the opposite of
string | number | bigint | boolean | symbol | undefined | null
.
Do not mistake it for Object
(with an uppercase O
), which refers to anything that can be indexed like an object and essentially complements of undefined | null
. For example, a string such as "foo"
has an apparent method like toUpperCase()
; calling "foo".toUpperCase()
wraps "foo"
in a String
object. If excluding primitives like string
, you should use object
instead of Object
.
In any case, this means that the call signature of clone()
should appear as follows:
export function clone<T extends object>(o: T): T {
return Object.setPrototypeOf({ ...o }, o.constructor.prototype);
}
By restricting the type parameter T
to object
, only non-primitive parameters for o
will be allowed:
clone(new Date()); // valid
clone({ a: 1, b: 2 }); // valid
clone([1, 2, 3]); // valid
clone("oops"); // invalid
clone(123); // invalid
clone(false); // invalid
clone(Symbol("wha")); // invalid
clone(undefined); // invalid
clone(null); // invalid
Link to playground with code