Typescript数组[T]接受{..T}作为有效类型

Typescript数组[T]接受{..T}作为有效类型,typescript,types,Typescript,Types,当我使用useState作为react钩子时,当我错误地键入{…options}而不是[…options]时,这让我感到有些不安,我只是在尝试访问“array”(对象)的.map时发现了一个类型错误。让我举一个例子来澄清我的问题: interface Option { title: string; isSelected?: boolean; } function myFunc(options: Option[]): void {} const options:

当我使用
useState
作为react钩子时,当我错误地键入
{…options}
而不是
[…options]
时,这让我感到有些不安,我只是在尝试访问“array”(对象)的
.map
时发现了一个类型错误。让我举一个例子来澄清我的问题:

  interface Option {
    title: string;
    isSelected?: boolean;
  }

  function myFunc(options: Option[]): void {}

  const options: Option[] = [{title: 'Male', isSelected: true}, {title: 'Female'}, {title: 'Other'}];
  const options2 = {...options};
  myFunc(options);
  myFunc(options2); // why isn't this an error ?
在上玩,似乎typescript认为
选项2
被定义为:

const options2: {
    [x: number]: Option;
    length: number;
    toString(): string;
    toLocaleString(): string;
    pop(): Option | undefined;
    push(...items: Option[]): number;
    concat(...items: ConcatArray<Option>[]): Option[];
    concat(...items: (Option | ConcatArray<...>)[]): Option[];
    ... 24 more ...;
    [Symbol.unscopables](): {
        ...;
    };
}
const选项2:{
[x:编号]:选项;
长度:数字;
toString():字符串;
toLocaleString():字符串;
pop():选项|未定义;
推送(…项:选项[]):编号;
concat(…项:ConcatArray[]):选项[];
concat(…项:(选项| ConcatArray)[]):选项[];
…还有24个。。。;
[符号.不可分割]():{
...;
};
}

因此,它实际上看起来像一个Option类型的数组
Option[]
。但是spread操作符实际上并不复制数组原型成员,而且新对象肯定不是数组。我想说这是typescript类型系统中的一个错误。

这似乎确实是typescript本身的一个问题:

let c: number[] = { ...[0, 1, 2] }; // compiles
c.fill(0) // runtime error

let d: number[] = Object.assign({}, [0, 1, 2]);  // compiles
d.fill(0) // runtime error
此外,这还会在运行时编译和中断:

class E {
    method() { }
}

let e: E = Object.assign({}, new E)
e.method() // runtime error

我想这是因为
Object.assign
被声明为

assign<T, U>(target: T, source: U): T & U;
assign(目标:T,来源:U):T&U;
这是不正确的,因为
assign
返回的内容实际上并不扩展
U
assign
的返回类型应该类似于
T&OwnProperties
,但这目前是不可能的,请参阅


很短:数组的类型是object,所以typescript不在乎,这意味着数组可以转换为object,反之亦然versa@MedetTleukabiluly当然,TS已经区分了
T[]
T
,所以它不像“数组是对象”那么简单,因为如果这是真的
T[]=T
如果
T
是对象。在本例中,似乎将数组视为相同的数组,但可能有一个选项来限制它。TypeScript的类型系统通常无法表示自己的或可枚举的属性,因此其对象扩展行为不安全。有一种方法试图在类型级别表示对象分布,并且提到了这个问题(请参阅和随后的注释)。我认为,目前还没有很好的答案。他们可能会说这是一个设计限制,而不是一个bug。是相关的对象扩散拉请求,它承认。