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

时间:2017-12-30 13:51:23

标签: 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
                       })        
    }    
}

我收到错误:

 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[]'.

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

来自:

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

到:

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

问题

为什么更改订单会使其编译?

Image proof

Typescript play ground demo

1 个答案:

答案 0 :(得分:2)

如果将StateKey enum中的字符串更改为其他值,则编译时没有错误,例如

export enum StateKey { backlogItems='somethingElse'}

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

编译器正在执行type inference并检测到[name]函数的参数中的next()只能backlogItems,其被声明为number[]。< / p>

因此,对象文字的两个变体都为同一属性分配了两个不同的值,这就是为什么赋值顺序很重要 - 最后一个基本上胜出。如果最后指定的值与声明的属性类型不兼容,编译器会报告错误 - Tnumber[]不兼容。

<强>更新

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

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     
                       })        
    }    
}