Typescript 为什么不';“我收到”吗;属性在X上不存在;在lambdas返回的对象上?

Typescript 为什么不';“我收到”吗;属性在X上不存在;在lambdas返回的对象上?,typescript,Typescript,当我意外地在对象上包含多余的属性时,通常会收到编译错误 不幸的是,在lambdas返回的对象上包含多余属性时,我似乎没有收到相同的错误 为什么会这样 接口Foo{ 条形图:布尔型; } 常量foo1:()=>Foo=()=>{ 返回{ 酒吧:错, iShouldNotBeHere:true//没有错误,为什么? }; }; 常量foo2=():Foo=>{ 返回{ 酒吧:错, iShouldNotBeHere:正确//错误!很好! }; }; 函数foo3():Foo{ 返回{ 酒吧:错, iS

当我意外地在对象上包含多余的属性时,通常会收到编译错误

不幸的是,在lambdas返回的对象上包含多余属性时,我似乎没有收到相同的错误

为什么会这样

接口Foo{
条形图:布尔型;
}
常量foo1:()=>Foo=()=>{
返回{
酒吧:错,
iShouldNotBeHere:true//没有错误,为什么?
};
};
常量foo2=():Foo=>{
返回{
酒吧:错,
iShouldNotBeHere:正确//错误!很好!
};
};
函数foo3():Foo{
返回{
酒吧:错,
iShouldNotBeHere:正确//错误!很好!
};
}

TypeScript版本4.1.2

称为 文字对象的处理方式与引用不同

对象文字得到特殊处理,并在将其分配给其他变量或作为参数传递时进行多余的属性检查。如果对象文字具有“目标类型”不具有的任何属性,您将得到一个错误

请参见下一个示例,它编译:

接口Foo{
条形图:布尔型;
}
函数foo1(f:((u:()=>Foo)=>Foo):void{
f(()=>({
酒吧:错,
iShouldNotBeHere:true//没有错误!为什么会发生这种情况?
}));
}
函数foo2(f:(:Foo)=>Foo:void{
常数结果={
酒吧:错,
伊苏尔德诺贝耶:是的
}
f(结果);
}
函数foo3():Foo{
常数结果={
酒吧:错,
伊苏尔德诺贝耶:是的
};
返回结果
}
更新

关于第一个示例,请参见文档中的引用:

或将其作为论点传递


尤萨林上尉的回答是对的,我今天回答了一个问题。但我认为我们两人都没有解释原因

仅当直接给具有未知属性的对象文本而不是预期类型时,过量属性检查才会给出错误直接是关键。因此,下面给出了一个错误:

interface MyType {
    myProp: string;
}

const myVar: MyType = {
    myProp: "myProp value",
    extra: "Not cool :/", // ERROR HERE
}
以下情况也是如此:

interface MyType {
    myProp: string;
}

const myFunc = (): MyType => ({
    myProp: "myProp value",
    extra: "Not cool :/", // ERROR HERE
});
interface MyType {
    myProp: string;
}

type MyFuncType = () => MyType;

const myFunc: MyFuncType = () => ({
    myProp: "myProp value",
    extra: "Not cool :/", // LOOK, NO ERROR!
});
但不包括以下内容:

interface MyType {
    myProp: string;
}

const myFunc = (): MyType => ({
    myProp: "myProp value",
    extra: "Not cool :/", // ERROR HERE
});
interface MyType {
    myProp: string;
}

type MyFuncType = () => MyType;

const myFunc: MyFuncType = () => ({
    myProp: "myProp value",
    extra: "Not cool :/", // LOOK, NO ERROR!
});
为什么??在最后一个示例中,
myFunc
是一个返回与预期的
MyType
兼容的对象类型的函数。因此,即使返回的对象类型不兼容,函数类型也是兼容的。这是因为,显然,超额属性检查仅针对即时分配(或返回)进行。

这是由于:

接口Foo{
foo:布尔;
}
接口条{
条形图:布尔型;
}
输入Foo1=()=>Foo;
输入Foo2=()=>Foo&Bar;
常量foo1:foo1=(空值为任意值)为Foo2;//无误差(协方差允许)
常量foo2:foo2=(空值为任意值)为Foo1;//错误
在OP的问题中,
foo1
是类型为
()=>Foo
的变量,但分配给它的是类型为
()=>Foo&{iShouldNotBeHere:boolean}
的对象,这是通过lambda类型方差允许的,如上所述

接口Foo{
条形图:布尔型;
}
常量foo1:()=>Foo=()=>{
返回{
酒吧:错,
iShouldNotBeHere:true//没有错误,为什么?
};
};
常量foo2=():Foo=>{
返回{
酒吧:错,
iShouldNotBeHere:正确//错误!很好!
};
};
这相当于写:

接口Foo{
条形图:布尔型;
}
接口条{
iShouldNotBeHere:布尔值;
}
const foo1:()=>Foo=():Foo&Bar=>{//协方差允许的lambda上溯
返回{
酒吧:错,
iShouldNotBeHere:true//无错误。
};
};
常量foo2=():Foo=>{
返回{
酒吧:错,
iShouldNotBeHere:true//Error。
};
};
更新:

以下ESLint规则将在返回对象文字的lambda上强制执行返回类型,这将为您解决此问题:


这可能是一个TypeScript错误。请看,这可能与参数必须精确有关,但返回值不必精确exact@CertainPerformance我添加了
foo3
,以表明这不是问题所在,请参见类似示例。这可能是一种神秘但已知的行为。如果是这样的话,我希望有一个标志来禁用它:我认为这并不能解释为什么在lambdas中放弃检查。文档说明,在“将它们分配给其他变量或将它们作为参数传递”时,会执行多余的检查。当然,它没有提到“从lambda返回”,但也没有提到“从函数返回”,但后者返回一个错误。只有前者没有。我认为这实际上是lambda类型上的返回类型(例如
Func
)在默认情况下是协变的,我通过使用ESlint规则
显式函数返回类型
allowExpressions:false
allowTypedFunctionExpressions:false
在所有lambda函数声明中强制显式返回类型来解决这个问题。