Typescript ';不可分配给类型为';对象文字错误

Typescript ';不可分配给类型为';对象文字错误,typescript,type-inference,Typescript,Type Inference,对象文字类型有问题 interface OptionalFoo { foo?: number; } interface Bar {} function foobarFn(foobar: OptionalFoo & Bar) {} foobarFn({ bar: 1 }); // error foobarFn({ bar: 1 } as { bar: number }); // ok foobarFn({ bar: 1 } as { bar: 1 }); // ok! 具有

对象文字类型有问题

interface OptionalFoo {
  foo?: number;
}

interface Bar {}

function foobarFn(foobar: OptionalFoo & Bar) {}

foobarFn({ bar: 1 }); // error

foobarFn({ bar: 1 } as { bar: number }); // ok

foobarFn({ bar: 1 } as { bar: 1 }); // ok!
具有推断类型的对象文字会导致类型错误:

类型为“{bar:number;}”的参数不能分配给类型为“OptionalFoo&bar”的参数

但问题不在于推理本身:

const bar = { bar: 1 }; // inferred { bar: number; }
foobarFn(bar); // ok!?
扩展语法与
对象有相同的问题。分配

foobarFn({...{ bar: 1 }}); // error

foobarFn(Object.assign({}, { bar: 1 })); // ok!?

是否有一种方法可以实现推断对象文字类型(多余属性检查)的行为,而无需就地对象文字,例如使用
bar
变量或函数调用,如
object.assign({bar:1})

只是为了弄清楚这不仅仅是多余的属性检查。当我们将一个对象文字直接指定给一个位置时,多余的属性检查就会起作用。在您的情况下,间接指定对象时会发生更令人惊讶的行为,这通常在过度的属性检查下是允许的

function foo(o: { bar: number }) { }
foo({ bar: 0, foo: "" }) // error direct assignment
foo({ bar:0, foo: ""} as { bar:0, foo: "" }) // ok indirect
令人惊讶的是,至少对我来说,另一个检查(弱类型检查)没有发现这个错误。在弱类型检查(如上所述)下,如果一个类型只有可选属性,并且我们试图分配一个与之没有共同属性的类型,我们将得到一个错误:

function foo(o: { bar?: number }) { }
foo({ foo: "" }) // error under excess properties:  Object literal may only specify known properties, and 'foo' does not exist in type
foo({ foo: ""} as { foo: "" }) // error under weak types: Type '{ foo: ""; }' has no properties in common with type '{ bar?: number; }'.
我认为这是弱类型检查中的一个漏洞(我不确定bug是否是设计的)。弱类型是(根据此):

  • 至少具有一个属性的对象类型
  • 其中所有属性都是可选的
  • 并且没有字符串索引签名、数字索引签名、调用签名或构造签名
  • 然而,在交叉口弱类型检查的实施过程中,所有类型的交叉口都必须是弱类型,才能使交叉口成为弱类型。来自编译器代码(添加注释):

    函数isWeakType(type:type):布尔型{
    if(type.flags和TypeFlags.Object){
    // ....
    }
    if(type.flags和TypeFlags.Intersection){
    ///所有交叉口成员都必须是弱的
    返回每个((type).types,isWeakType);
    }
    返回false;
    }
    

    由于
    接口栏{}
    不是弱类型(根据第一条规则,它没有属性),因此与它的任何交集都不会是弱类型,也不会引发任何弱类型检查错误。从交叉点删除
    条形图
    会在指定与目标没有共同点的对象的任何地方引发错误。

    @JBNizet谢谢您的参考,完全忘记了这个术语。是的,就是这样。我想知道是否有可能在TS没有应用的地方触发多余的属性检查,比如当一个对象作为变量传递时。@estus,不仅仅是这样。。我认为这是关于弱类型的…这需要运行时检查,而不是编译时检查。谢谢,很好的解释。我们还发现,检查至少可以在需要时通过价差触发,
    foobarFn({…bar})
    function isWeakType(type: Type): boolean {
        if (type.flags & TypeFlags.Object) {
           // ....
        }
        if (type.flags & TypeFlags.Intersection) {
            /// All intersection members have to be weak
            return every((<IntersectionType>type).types, isWeakType); 
        }
        return false;
    }