有没有办法在TypeScript中定位纯JavaScript对象类型?

Zol*_*ási 8 javascript typescript typescript2.1

我正在尝试编写一个函数,我想表明它返回某种纯JavaScript对象.对象的签名是未知的,现在不是很有趣,只是它是一个普通的对象.我的意思是一个普通的对象,它满足例如jQuery的isPlainObject功能.例如

{ a: 1, b: "b" }
Run Code Online (Sandbox Code Playgroud)

是一个普通的对象,但是

var obj = new MyClass();
Run Code Online (Sandbox Code Playgroud)

不是一个"普通"的对象,因为它constructor不是Object.jQuery做了一些更精确的工作$.isPlainObject,但这不是问题的范围.

如果我尝试使用Object类型,那么它也将与任何自定义对象兼容,因为它们是继承自的Object.

有没有办法在TypeScript中定位"普通对象"类型?

我想要一个类型,例如满足这个.

var obj: PlainObject = { a: 1 }; // perfect
var obj2: PlainObject = new MyClass(); // compile-error: not a plain object
Run Code Online (Sandbox Code Playgroud)

用例

对于服务器端方法,我有一种强类型的存根,就像这样.这些存根是由我的一个代码生成器生成的,基于ASP.NET MVC控制器.

export class MyController {
  ...
  static GetResult(id: number): JQueryPromise<PlainObject> {
    return $.post("mycontroller/getresult", ...);
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

现在,当我在消费者类中调用它时,我可以做这样的事情.

export class MyViewModelClass {
  ...
  LoadResult(id: number): JQueryPromise<MyControllerResult> { // note the MyControllerResult strong typing here
    return MyController.GetResult(id).then(plainResult => new MyControllerResult(plainResult));
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

现在想象一下控制器方法返回JQueryPromise<any>JQueryPromise<Object>.而现在也想象我偶然写的done而不是then.现在我有一个隐藏的错误,因为viewmodel方法不会返回正确的promise,但我不会得到编译错误.

如果我有这个虚构PlainObject类型,我希望得到一个编译错误,指出PlainObject无法转换为MyControllerResult或类似的东西.

gpr*_*and 9

在 TypeScript 3.7.2 中测试:

对于平面对象,您可以执行以下操作:

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
Run Code Online (Sandbox Code Playgroud)

对于嵌套的普通对象:

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
Run Code Online (Sandbox Code Playgroud)

代码改编自https://github.com/microsoft/TypeScript/issues/3496#issuecomment-128553540


Nit*_*mer 8

在我的代码中,我有一些与您所要求的类似的内容:

export type PlainObject = { [name: string]: any }
export type PlainObjectOf<T> = { [name: string]: T }
Run Code Online (Sandbox Code Playgroud)

我也有一个类型保护:

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

编辑

好的,我明白你在寻找什么,但不幸的是这是不可能的。
如果我理解正确的话,那么这就是你所追求的:

type PlainObject = {
    constructor: ObjectConstructor;
    [name: string]: any
}
Run Code Online (Sandbox Code Playgroud)

问题是在“lib.d.ts”中对象的定义如下:

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

然后是这个:

let o: PlainObject = { key: "value" };
Run Code Online (Sandbox Code Playgroud)

结果有错误:

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'.
Run Code Online (Sandbox Code Playgroud)