[英]Is there any way to convert Ember Object into plain javascript object?
[英]Is there any way to target the plain JavaScript object type in TypeScript?
對於使用較新功能的有效解決方案,請參閱此答案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
與接受的答案的不同之處在於,它還允許普通 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'.
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.