# 类型判断

# 题目

实现一个 getType 函数,传入一个变量,能准确的获取它的类型。 如 number string function object array map regexp 等。

# 类型判断

常规的类型判断一般用 typeofinstanceof ,但这俩也有一些缺点

  • typeof 无法继续区分 object 类型
  • instanceof 需要知道构造函数,即需要两个输入

# 枚举不是好方法

你可能觉得 typeofinstanceof 结合起来可以判断,枚举所有的类型。
这并不是一个好方法,因为手动枚举是不靠谱的,不具备完整性。
第一,你有可能忽略某些类型,如;第二,ES 有会继续增加新的类型,如 Symbol BigInt

function getType(x: any): string {
    if (typeof x === 'object') {
        if (Array.isArray(x)) return 'array'
        if (x instance of Map) return 'map'
        // 继续枚举...
    }
    return typeof x
}

# 使用 Object.prototype.toString

注意,必须用 Object.prototype.toString ,不可以直接用 toString。后者可能是子类重写的。

[1, 2].toString() // '1,2' ( 这样使用的其实是 Array.prototype.toString )
Object.prototype.toString.call([1, 2]) // '[object Array]'
/**
 * 获取详细的数据类型
 * @param x x
 */
export function getType(x: any): string {
    const originType = Object.prototype.toString.call(x) // '[object String]'
    const spaceIndex = originType.indexOf(' ')
    const type = originType.slice(spaceIndex + 1, -1) // 'String'
    return type.toLowerCase() // 'string'
}

# 单元测试

import { getType } from "./get-type";

describe("获取详细的数据类型", () => {
    it("null", () => {
        expect(getType(null)).toBe("null");
    });
    it("undefined", () => {
        expect(getType(undefined)).toBe("undefined");
    });
    it("number", () => {
        expect(getType(100)).toBe("number");
        expect(getType(NaN)).toBe("number");
        expect(getType(Infinity)).toBe("number");
        expect(getType(-Infinity)).toBe("number");
    });
    it("string", () => {
        expect(getType("abc")).toBe("string");
    });
    it("boolean", () => {
        expect(getType(true)).toBe("boolean");
    });
    it("symbol", () => {
        expect(getType(Symbol())).toBe("symbol");
    });
    it("bigint", () => {
        expect(getType(BigInt(100))).toBe("bigint");
    });
    it("object", () => {
        expect(getType({})).toBe("object");
    });
    it("array", () => {
        expect(getType([])).toBe("array");
    });
    it("function", () => {
        expect(getType(() => {})).toBe("function");
        expect(getType(class Foo {})).toBe("function");
    });
    it("map", () => {
        expect(getType(new Map())).toBe("map");
    });
    it("weakmap", () => {
        expect(getType(new WeakMap())).toBe("weakmap");
    });
    it("set", () => {
        expect(getType(new Set())).toBe("set");
    });
    it("weakset", () => {
        expect(getType(new WeakSet())).toBe("weakset");
    });
    it("date", () => {
        expect(getType(new Date())).toBe("date");
    });
    it("regexp", () => {
        expect(getType(new RegExp(""))).toBe("regexp");
    });
    it("error", () => {
        expect(getType(new Error())).toBe("error");
    });
    it("promise", () => {
        expect(getType(Promise.resolve())).toBe("promise");
    });
});