【问题标题】:Typescript Array[T] accepts {..T} as valid typeTypescript Array[T] 接受 {..T} 作为有效类型
【发布时间】:2019-10-15 22:48:26
【问题描述】:

当我使用 useState<Options[]> 作为反应钩子时,当我输入错误 {...options} 而不是 [...options] 时,我只是在尝试访问“数组”(对象)的 .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 ?

【问题讨论】:

  • 短:typeof数组是对象,所以打字稿不关心,意思是数组可以转换为对象,反之亦然
  • @MedetTleukabiluly 肯定 TS 已经区分了 T[]T,所以它不像“数组是对象”那么简单,因为如果这是真的 T[] = T 如果 T 是一个对象。从 this example 来看,它似乎将类似数组的数组视为相同,但可能有一个选项来限制它。

标签: typescript types


【解决方案1】:

这似乎确实是 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

PG

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

assign<T, U>(target: T, source: U): T & U;

这是不正确的,因为assign 返回的内容实际上并没有扩展Uassign 的返回类型应该是 T &amp; OwnProperties&lt;U&gt; 之类的东西,但目前还不可能,请参阅

【讨论】:

  • TypeScript 的类型系统通常无法表示自己的或可枚举的属性,因此它的对象传播行为是不安全的。有一个proposal 试图在类型级别表示对象传播,并提到了这个问题(参见this 和后续的cmets)。我想,目前还没有很好的答案。
【解决方案2】:

typescript playground上玩,似乎打字稿认为options2被定义为:

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](): {
        ...;
    };
}

所以,它实际上看起来像一个 Option Option[] 类型的数组。但是扩展运算符实际上并没有复制 Array 原型成员,并且新对象绝对不是数组。我会说这是打字稿类型系统中的一个错误。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-24
  • 1970-01-01
  • 2020-08-22
相关资源
最近更新 更多