簡體   English   中英

有什么方法可以針對 TypeScript 中的普通 JavaScript object 類型嗎?

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

2021 年更新

對於使用較新功能的有效解決方案,請參閱此答案https://stackoverflow.com/a/59647842/1323504


我正在嘗試編寫一個 function,我想指出它返回某種普通的JavaScript object。該對象的簽名未知,目前並不有趣,只是它是一個普通的 object。我的意思是一個普通的object 滿足例如 jQuery 的isPlainObject function。例如

{ a: 1, b: "b" }

是一個普通的 object,但是

var obj = new MyClass();

不是“普通”object,因為它的constructor不是Object jQuery 在$.isPlainObject中做了一些更精確的工作,但這與 scope 無關。

如果我嘗試使用Object類型,那么它也將與任何自定義對象兼容,因為它們是從Object繼承的。

有沒有辦法在 TypeScript 中定位“普通對象”類型?

我想要一個type ,它可以滿足這個要求。

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

用例

我有一種用於服務器端方法的強類型存根,就像這樣。 這些存根由我的一個代碼生成器生成,基於 ASP.NET MVC 控制器。

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

現在當我在消費者 class 中調用它時,我可以做這樣的事情。

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

現在假設 controller 方法返回JQueryPromise<any>JQueryPromise<Object> 現在還想象一下,我不小心寫done而不是then 現在我有一個隱藏錯誤,因為 viewmodel 方法不會返回正確的 promise,但我不會得到編譯錯誤。

如果我有這個虛構PlainObject類型,我希望得到一個編譯錯誤,指出PlainObject無法轉換為MyControllerResult或類似的東西。

在 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

對於嵌套的普通對象:

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

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

在我的代碼中,我有一些類似於您要問的內容:

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

我也有一個類型保護:

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

編輯

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

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

問題是在 'lib.d.ts' 對象是這樣定義的:

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

    ...
}

然后這個:

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

結果有錯誤:

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'.

您可以嘗試遞歸類型(幼稚的解決方案)

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

不好,不可怕:)

我發現這適用於 TS 4.9:

type PlainObject = Record<string, {}>;

class MyClass {}

function test(one: PlainObject) {}
test({ a: 1, b: "a", c: new MyClass() }); // OK
test(1); // Error
test("a"); // Error
test([1, 2, 3]); // Error
test(new Date()); // Error
test(new Map()); // Error
test(new Set()); // Error
test(new MyClass()); // Error

TS 游樂場鏈接

與接受的答案的不同之處在於,它還允許普通 object 包含復雜的值,而不僅僅是基元:

type ObjectOfPrimitives = Record<string, Primitive>;

function test(one: ObjectOfPrimitives) {}

test({ 
  a: 1, 
  b: "a", 
  c: new MyClass(), // Error: Type 'MyClass' is not assignable to type 'ObjectOfPrimitives'.
}); 

TS 游樂場鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM