简体   繁体   English

Typescript是否介意Object literal中的实例化顺序?

[英]Typescript mind the order of instantiation in an Object literal?

I'm using the latest Typescript version : 2.6.2 . 我正在使用最新的Typescript版本: 2.6.2

I'm encountering a bizarre situation where if I do foo({a:1,b:2}) - things don't work whereas if I do : foo({b:2,a:1}) - they do work. 我遇到了一个奇怪的情况,如果我做foo({a:1,b:2}) - 事情不起作用,如果我这样做: foo({b:2,a:1}) - 他们确实有效。

I have a generic class , an interface which has 2 properties and a function. 我有一个泛型类,一个有2个属性和一个函数的接口。

Here is the code : 这是代码:

class MyClass<T>  {
    value: T;
    next(value: T): void {
  }
}


export enum StateKey { backlogItems='backlogItems'}


export interface State {
    backlogItems : number[];
    [key: string]: any
}

class A {

    private subj = new MyClass<State>();

    public set<T>(name: StateKey, state: T) {
        this.subj.next({  backlogItems: [...this.subj.value.backlogItems] ,
                         [name]:state      //<--- error here
                       })        
    }    
}

I get an error : 我收到一个错误:

  Argument of type '{ [name]: T; }' is not assignable to parameter of type 'State'. Types of property 'backlogItems' are incompatible. Type 'T' is not assignable to type 'number[]'. 

But If I change the order of the literals in the object : 但是如果我改变对象中文字的顺序:

from : 来自:

this.subj.next({ backlogItems: [...this.subj.value.backlogItems], [name]: state })

to : 至 :

 this.subj.next({ [name]:state, backlogItems: [...this.subj.value.backlogItems] })
  • Then there's no error 然后没有错误

Question

Why does changing the order makes it compile ? 为什么更改顺序会使其编译?

Image proof 图像证明

Typescript play ground demo 打字稿演示地面演示

It compiles without errors if you change the string in StateKey enum to some other value, like this 如果将StateKey枚举中的字符串更改为其他值,则编译时没有错误,如下所示

export enum StateKey { backlogItems='somethingElse'}

(the error also goes away if you add more values to the enum) (如果向枚举添加更多值,错误也会消失)

The compiler is doing type inference and detects that [name] in your argument to next() function can be only backlogItems , which is declared as number[] . 编译器正在进行类型推断并检测到next()函数的参数中的[name]只能是backlogItems ,它被声明为number[]

So both variants of the object literal are assigning two different values to the same property, that's why order of assignment matters - the last one wins, basically. 因此,对象文字的两个变体都为同一属性分配了两个不同的值,这就是为什么赋值顺序很重要 - 最后一个基本胜利。 Compiler reports the error in case when the last assigned value is incompatible with declared property type - T is not compatible with number[] . 如果最后一个赋值与声明的属性类型不兼容,编译器会报告错误 - Tnumber[]不兼容。

UPDATE UPDATE

Also, to preserve the code and just get rid of the error, you can make the compiler forget about the type it inferred for name by assigning it to the intermediate variable with string type: 此外,为了保留代码并消除错误,您可以通过将其分配给具有string类型的中间变量,使编译器忘记它为name推断的类型:

class MyClass<T>  {
    value: T;
    next(value: T): void {
  }
}


export enum StateKey { backlogItems='backlogItems'}


export interface State {
    backlogItems : number[];
    [key: string]: any
}

class A {

    private subj = new MyClass<State>();

    public set<T>(name: StateKey, state: T) {
        const key: string = name;
        this.subj.next({  backlogItems: [...this.subj.value.backlogItems] ,
                         [key]:state     
                       })        
    }    
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM