TypeScript-非数组对象的定义/接口

时间:2018-07-09 05:39:47

标签: typescript typescript2.0 tsc

我为JS / JSON.stringify的这一功能而烦恼:

const v = [];
v.foo = 5;
v.start = true;
console.log(JSON.stringify({value: v}));

您将在控制台中找到它:

{"value":[]}

所以我要创建的类型是对象而不是数组:

export const acceptsObjectsButNotArrays = function(v: MyType){
  v[marker] = true;
  console.log(JSON.stringify({value:v});
}

使用TS,是否可以为MyType使用定义,以确保它是对象而不是数组?

export interface ObjectButNotArray extends Object {
  [key:string]: any
}

它需要像上面一样具有索引签名,所以我可以为其添加任意属性。

我能想到的最接近的东西是:

export type ObjectButNotArray = object & !Array<any>

尽管语法是伪造的。

1 个答案:

答案 0 :(得分:1)

数组是对象,所以基本上我们希望在需要基本类型的地方不允许使用派生类型,这在OOP术语中并不是很确定。

您不能直接定义这样的类型,但是可以使用条件类型来确保函数不接受数组作为参数,方法是在传入数组时创建不兼容性。如果参数是数组,则我们强加对参数的额外限制,实际上使参数无法(或至少不可能)传递。

export const acceptsObjectsButNotArrays = function <T extends { [n: string]: any }>(v: T & ErrorIfArray<T>) {
    v["marker"] = true;
    console.log(JSON.stringify({ value: v }));
}

type ErrorIfArray<T> = T extends any[] ? "Argument must be an array" : T;

acceptsObjectsButNotArrays({ // ok
    a: ""
});
acceptsObjectsButNotArrays([]); // Type 'undefined[]' is not assignable to type '"Argument must be an array"'.