Is there any way to target the plain JavaScript object type in TypeScript?

前端 未结 3 1041
梦谈多话
梦谈多话 2021-02-13 09:46

I\'m trying to write a function where I\'d like to indicate that it returns some kind of plain JavaScript object. The object\'s signature is unknown, and not interestin

相关标签:
3条回答
  • 2021-02-13 10:10

    You can try recursive type (naive solution)

    type SerializableObject = { [x: string]: SerializableObject | number | string | [] };
    

    Not good, not terrible :)

    0 讨论(0)
  • 2021-02-13 10:15

    Tested in TypeScript 3.7.2:

    For a flat plain object, you can do:

    type Primitive =
      | bigint
      | boolean
      | null
      | number
      | string
      | symbol
      | undefined;
    
    type PlainObject = Record<string, Primitive>;
    
    class MyClass {
      //
    }
    
    const obj1: PlainObject = { a: 1 }; // Works
    const obj2: PlainObject = new MyClass(); // Error
    

    For a nested plain object:

    type Primitive =
      | bigint
      | boolean
      | null
      | number
      | string
      | symbol
      | undefined;
    
    type JSONValue = Primitive | JSONObject | JSONArray;
    
    interface JSONObject {
      [key: string]: JSONValue;
    }
    
    interface JSONArray extends Array<JSONValue> { }
    
    const obj3: JSONObject = { a: 1 }; // Works
    const obj4: JSONObject = new MyClass(); // Error
    
    const obj5: JSONObject = { a: { b: 1 } }; // Works
    const obj6: JSONObject = { a: { b: { c: 1 } } }; // Works
    const obj7: JSONObject = { a: { b: { c: { d: 1 } } } }; // Works
    

    Code is an adaptation from https://github.com/microsoft/TypeScript/issues/3496#issuecomment-128553540

    0 讨论(0)
  • 2021-02-13 10:22

    In my code I have something similiar to what you're asking:

    export type PlainObject = { [name: string]: any }
    export type PlainObjectOf<T> = { [name: string]: T }
    

    And I also have a type guard for that:

    export function isPlainObject(obj: any): obj is PlainObject {
        return obj && obj.constructor === Object || false;
    }
    

    Edit

    Ok, I understand what you're looking for, but unfortunately that is not possible.
    If i understand you correctly then this is what you're after:

    type PlainObject = {
        constructor: ObjectConstructor;
        [name: string]: any
    }
    

    The problem is that in 'lib.d.ts' Object is defined like so:

    interface Object {
        /** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
        constructor: Function;
    
        ...
    }
    

    And then this:

    let o: PlainObject = { key: "value" };
    

    Results with an error:

    Type '{ key: string; }' is not assignable to type 'PlainObject'.
      Types of property 'constructor' are incompatible.
        Type 'Function' is not assignable to type 'ObjectConstructor'.
          Property 'getPrototypeOf' is missing in type 'Function'.
    
    0 讨论(0)
提交回复
热议问题