A better typeof
The typeof operator is a really useful one but it has a few pitfalls:
typeof ["an", "array"] // object
typeof /regex/g // object
typeof null // object
typeof var NaN: numberNaN // number
typeof var Number: NumberConstructor
(value?: any) => numberAn object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers.Number('I am not a number!') // number
Ok, that's a lot of pitfalls;
But there is a way to get more detailed types using Object.prototype.toString.call() on a value:
// This statement basically means: "Call the toString method of the object prototype on whatever value you like"
var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<{
object: string;
}, [], string>(this: (this: {
object: string;
}) => string, thisArg: {
object: string;
}): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call({ object: stringobject: "true" }) // the infamous [object Object]
var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<string[], [], string>(this: (this: string[]) => string, thisArg: string[]): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call(["an", "array"]) // [object Array]
var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<string, [], string>(this: (this: string) => string, thisArg: string): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call("a string") // [object String]
var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<bigint, [], string>(this: (this: bigint) => string, thisArg: bigint): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call(1n) // [object Bigint]
var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<Date, [], string>(this: (this: Date) => string, thisArg: Date): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call(new var Date: DateConstructor
new () => Date (+4 overloads)Date()) // [object Date] really
var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<Error, [], string>(this: (this: Error) => string, thisArg: Error): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call(new var Error: ErrorConstructor
new (message?: string | undefined, options?: ErrorOptions | undefined) => Error (+1 overload)Error("an error")) // [object Error]
var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<() => void, [], string>(this: (this: () => void) => string, thisArg: () => void): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call(function () {}) // [object Function]
var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<() => Generator<never, void, unknown>, [], string>(this: (this: () => Generator<never, void, unknown>) => string, thisArg: () => Generator<never, void, unknown>): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call(function* () {}) // [object GeneratorFunction]
var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<RegExp, [], string>(this: (this: RegExp) => string, thisArg: RegExp): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call(/regex/gi) // [object RegExp]
var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<symbol, [], string>(this: (this: symbol) => string, thisArg: symbol): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call(var Symbol: SymbolConstructor
(description?: string | number | undefined) => symbolReturns a new unique Symbol value.Symbol()) // [object Symbol]
var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<number, [], string>(this: (this: number) => string, thisArg: number): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call(var NaN: numberNaN) // it's not perfect: [object Number]
Of course, this could be made a function (with a few finishing touches from here)
function function type(obj: any, showFullClass?: boolean): stringtype(obj: anyobj: any, showFullClass: booleanshowFullClass = false) {
// Whether to return the whole type
if (showFullClass: booleanshowFullClass && typeof obj: anyobj === "object") {
return var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<any, [], string>(this: (this: any) => string, thisArg: any): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call(obj: anyobj);
}
if (obj: anyobj == null) { return (obj: anyobj + '').String.toLowerCase(): stringConverts all the alphabetic characters in a string to lowercase.toLowerCase(); } // implicit toString() conversion
if (var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.is(value1: any, value2: any): booleanReturns true if the values are the same value, false otherwise.is(obj: anyobj, var NaN: numberNaN)) return "nan";
var function (local var) deepType: stringdeepType = var Object: ObjectConstructorProvides functionality common to all JavaScript objects.Object.ObjectConstructor.prototype: ObjectA reference to the prototype for a class of objects.prototype.Object.toString(): stringReturns a string representation of an object.toString.CallableFunction.call<any, [], string>(this: (this: any) => string, thisArg: any): stringCalls the function with the specified object as the this value and the specified rest arguments as the arguments.call(obj: anyobj).String.slice(start?: number | undefined, end?: number | undefined): stringReturns a section of a string.slice(8,-1).String.toLowerCase(): stringConverts all the alphabetic characters in a string to lowercase.toLowerCase();
if (function (local var) deepType: stringdeepType === 'generatorfunction') { return 'function' }
// Prevent overspecificity (for example, [object HTMLDivElement], etc).
// Account for functionish Regexp (Android <=2.3), functionish <object> element (Chrome <=57, Firefox <=52), etc.
// String.prototype.match is universally supported.
return function (local var) deepType: stringdeepType.String.match(matcher: {
[Symbol.match](string: string): RegExpMatchArray | null;
}): RegExpMatchArray | null (+1 overload)Matches a string or an object that supports being matched against, and returns an array
containing the results of that search, or null if no matches are found.match(/^(array|bigint|date|error|function|generator|regexp|symbol)$/) ? function (local var) deepType: stringdeepType :
(typeof obj: anyobj === 'object' || typeof obj: anyobj === 'function') ? 'object' : typeof obj: anyobj;
}