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