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

Roy*_*mir 7 javascript typescript

我正在使用最新的Typescript版本:2.6.2.

我遇到了一个奇怪的情况,如果我这样做foo({a:1,b:2})- 事情不起作用,而如果我这样做: foo({b:2,a:1})- 他们确实有效.

我有一个泛型类,一个有2个属性和一个函数的接口.

这是代码:

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
                       })        
    }    
}
Run Code Online (Sandbox Code Playgroud)

我收到一个错误:

 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[]'.
Run Code Online (Sandbox Code Playgroud)

但是如果我改变对象中文字的顺序:

来自:

this.subj.next({ backlogItems: [...this.subj.value.backlogItems], [name]: state })
Run Code Online (Sandbox Code Playgroud)

至 :

 this.subj.next({ [name]:state, backlogItems: [...this.subj.value.backlogItems] })
Run Code Online (Sandbox Code Playgroud)
  • 然后没有错误

为什么更改顺序会使其编译?

图像证明

打字稿演示地面演示

art*_*tem 2

如果将枚举中的字符串更改StateKey为其他值,则编译不会出现错误,如下所示

export enum StateKey { backlogItems='somethingElse'}
Run Code Online (Sandbox Code Playgroud)

(如果向枚举添加更多值,错误也会消失)

编译器正在进行类型推断,并检测[name]到函数的参数next()只能是backlogItems,它被声明为number[]

因此,对象字面量的两种变体都将两个不同的值分配给同一个属性,这就是分配顺序很重要的原因 - 基本上最后一个获胜。如果最后分配的值与声明的属性类型不兼容 -T与 不兼容,编译器会报告错误number[]

更新

另外,为了保留代码并消除错误,您可以name通过将类型分配给中间变量来让编译器忘记它推断的string类型:

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     
                       })        
    }    
}
Run Code Online (Sandbox Code Playgroud)