Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 具有并集和对象类型的不一致类型脚本行为_Typescript - Fatal编程技术网

Typescript 具有并集和对象类型的不一致类型脚本行为

Typescript 具有并集和对象类型的不一致类型脚本行为,typescript,Typescript,让我们看一下下面的片段: interface A { isEmpty(x: any[] | string | object): boolean; isEmptyObject(x: object): boolean; } const a: A = <A>{}; a.isEmptyObject({}); a.isEmptyObject({a: 1}); a.isEmpty([]); a.isEmpty(''); a.isEmpty({}); a.isEmpty({a: 1}

让我们看一下下面的片段:

interface A {
  isEmpty(x: any[] | string | object): boolean;
  isEmptyObject(x: object): boolean;
}

const a: A = <A>{};

a.isEmptyObject({});
a.isEmptyObject({a: 1});

a.isEmpty([]);
a.isEmpty('');
a.isEmpty({});
a.isEmpty({a: 1});
当联合类型(
string | object | any[]
)包含其工作的类型
object
(使用
{a:1}
调用
isEmptyObject
很好)时,这怎么可能呢

主要问题:这是一个TypeScript错误,还是应该如何编写输入可以是任何值、字符串或对象的数组(但不是任何原语,我不想要
任何
对象


使用TypeScript 2.3.4进行测试。

TypeScript在以下情况下编译失败:

Object literal只能指定已知属性,而'string | Object | any[]类型中不存在'a'。

基本上,
{a:1}
不能转换为类型
对象

你可以这样做:

interface A {
    isEmpty(x: any[] | string | { [index: string]: any }): boolean;
    isEmptyObject(x: { [index: string]: any }): boolean;
}
编辑:再看一眼后,可能会解释为:

联合类型在这里可能有点棘手,但需要一点直觉来适应。如果一个值的类型是a | B,我们只能确定它有a和B都有的成员。在本例中,Bird有一个名为fly的成员。我们无法确定类型为Bird | Fish的变量是否有fly方法。如果变量在运行时真的是鱼,那么调用pet.fly()将失败


您可以通过添加另一个签名轻松解决此问题:

interface A {
    isEmpty(x: any[]): boolean;
    isEmpty(x: string | object): boolean;
    isEmptyObject(x: object): boolean;
}

a.isEmpty({ a: 1 }); // fine now
function isEmptyObject(x : object) : void;
()


编辑 我不认为这是一个bug,如果有什么是bug的话,那就是错误消息,它不是很有帮助

我认为发生的情况是,您可以在与任何基元类型的联合中使用
object
,而不会出现问题(在您的情况下),但一旦引入非基元类型,就会出现错误,例如:

isEmpty(x: string | object | Map<string, string>): boolean;
isEmpty(x:string | object | Map):布尔;
将导致相同的错误。
对象
(它是任何非基本类型)和另一个非基本类型的联合可能会导致无法匹配的类型,编译器会感到困惑


欢迎您在本案例中打开一个新问题,如果您打开了,请在此处共享链接,我想看看他们怎么说。

这不是一个bug,而是一个支持API-s的功能,它利用参数对象。以jQuery-s ajax函数为例。它以一个对象作为参数

interface JQueryAjaxParam {
    url: string;
    data?: any;
}

...

$.ajax({
    url: "",
    datta: "" // notice the typo here
});
尽管
{url:,datta:}
实现了param接口,但在这种情况下您确实希望出现编译错误。为了克服这个问题,他们补充道这是一件好事,它为typechecker提供了更多的信心,并且只会在人们试图进行像您这样的快速测试时导致错误。你必须记住这条规则,这是额外安全的代价

更新:TypeScript 2.4另外引入

因此,还有一些具有此签名的函数:

interface A {
    isEmpty(x: any[]): boolean;
    isEmpty(x: string | object): boolean;
    isEmptyObject(x: object): boolean;
}

a.isEmpty({ a: 1 }); // fine now
function isEmptyObject(x : object) : void;
在这里,意图很清楚,此函数旨在接受任何具有任何键的对象。只接受空对象的函数没有什么用处。因此,他们添加了一个例外:当参数的类型为
object
时,前面的检查被忽略

那怎么办呢?没有什么。在实际使用中,您的功能将很好地进行类型检查。你可以试试:

interface A {
  isEmpty(x: any[] | string | object): boolean;
  isEmptyObject(x: object): boolean;
}

const a: A = <A>{};
const param = {a: 1};

a.isEmptyObject({});
a.isEmptyObject(param);

a.isEmpty([]);
a.isEmpty('');
a.isEmpty({});
a.isEmpty(param);
接口A{
isEmpty(x:any[]| string | object):布尔值;
isEmptyObject(x:object):布尔值;
}
常数a:a={};
常量参数={a:1};
a、 isEmptyObject({});
a、 isEmptyObject(参数);
a、 isEmpty([]);
a、 isEmpty(“”);
a、 等空({});
a、 等空(param);
更新

您的示例是一个实际的用例,您希望它甚至可以与文本一起工作。在Nitzan之后,我也建议为此使用函数重载

interface A {
    isEmpty(x: any[]): boolean;
    isEmpty(x: string): boolean;
    isEmpty(x: object): boolean;
    isEmptyObject(x: object): boolean;
}

const a: A = <A>{};
a.isEmptyObject({b: 6});
a.isEmptyObject({a: 1});

a.isEmpty([]);
a.isEmpty('');
a.isEmpty({});
a.isEmpty({a: 1});
接口A{
isEmpty(x:any[]):布尔值;
isEmpty(x:string):布尔值;
isEmpty(x:object):布尔型;
isEmptyObject(x:object):布尔值;
}
常数a:a={};
a、 isEmptyObject({b:6});
a、 isEmptyObject({a:1});
a、 isEmpty([]);
a、 isEmpty(“”);
a、 等空({});
a、 等空({a:1});


这不可能是真的-
{a:1}
显然可以转换为
对象
,因为
a.isEmptyObject({a:1})在没有任何警告或错误的情况下工作。对于较大的块,请使用缩进而不是反勾号格式化代码。背景标记使得任何较大的块都无法读取。嗯,再看一眼文档,我认为这是由于联合类型将“any[]和object”组合在一起的方式。看我的edit@SeanSobey文档中的引用似乎与union类型的变量/参数的使用有关-我没有在任何地方使用
x
,这是唯一的接口(显示它如何不通过类型检查)。@adiga我看不出这有什么关系。我没有从属于联合类型的
x
参数访问任何字段。重新排列联合类型会改变什么吗?不知道为什么会这样,但我现在很好奇。@monnef抱歉。我意识到了这一点并删除了它it@Carcigenicate我在操场上试过,但这个命令似乎没有任何效果:-/@monnef Damn。我只用了一个月的TS,所以我只是在黑暗中拍摄。看起来像一个bug,但这不是第一个看起来像bug的东西,但实际上是TS的一些附带案例。但是为什么这是必要的?所以它是一个打字脚本bug?或者我为什么要跳过这些障碍?@Carcigenicate&OP检查我的修订答案这是一个真正的用途-我正在从库包装一个现有函数来修复打字。我需要任何类型、字符串或非原语(
对象
)的数组。当
对象被定义为非原语时,我看不出有什么理由希望它表示“仅空对象”。当类型检查是不可传递的时,这对我来说并不是一件好事。所以这与
suppressExcessPropertyErrors
编译器选项有关?@monnef我明白你的意思。让我做一点实验,更新我的answer@cartant也许,我不知道那个编译器选项。听起来像是。看起来它实际上是一个类型错误