Typescript中自定义数组类型的问题(缺少属性“flat”)

chhkpiq4  于 2022-11-30  发布在  TypeScript
关注(0)|答案(1)|浏览(186)

我正在用TypeScript 4.4.4构建我自己的数组类型。首先我创建了一个扩展“Array”的新类。经过一些研究,我发现这并不理想,但它起作用了。
我试图找到一些关于我的问题的信息,但总是在文章中结束,并不完全反映我的情况和问题。
现在,我尝试使用以下内容创建它:

export class DBModelCollection<T extends DBModel> implements Iterable<T> {
    
      private _items: Array<T>;
      constructor(arrayLength: number = 0) {
        this._items = new Array<T>(arrayLength);
      }

      [Symbol.iterator](): Iterator<T> {
       return this._items[Symbol.iterator]();
      }

      /* all member functions implemented except for 'flat' */
    }

所以我确信只将我的DBModel类作为项。这很好用。
然而,当使用这样的构造时,事情会出错。

class User extends DBModel { }

  const somelist: Array<User>;
  const otherlist: DBModelCollection<User> = new DBModelCollection<User>();

  otherlist.push(new User());

  somelist = otherlist; /* this generates an error */

  somelist = otherlist.filter(x => x.name === 'martin'); /* this generates an error */

错误为:TS 2741:类型“DBModelCollection”中缺少属性“flat,”但类型“User[]”中需要该属性.
我的代码里有很多这样的赋值语句。
我所尝试的是:

get flat():T[] {
    return this._items;
  }

然后错误发生变化:

TS2322: Type 'DBModelCollection<User>' is not assignable to type 'SecurityObjects[]'.The types of 'filter(...).flat' are incompatible between these types.

Type 'User[]' is not assignable to type '<A, D extends number = 1>;(this: A, depth?: D) => FlatArray<A, D>[]'.

Type 'SecurityObjects[]' provides no match for the signature '<A, D extends number = 1>;(this: A, depth?: D): FlatArray<A, D>[]'.

所以这太简单了。然后用IDE(jetbrains)在原来的flat函数的基础上为我生成了它:

flat<T, D = 1 >(depth?: D): FlatArray<T, number>[] {
    return this._items.flat(depth);
  }

这会产生一个巨大的错误:

TS2322: Type 'FlatArray<T, 0 | 1 | -1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20>[]' is not assignable to type '(T extends readonly (infer InnerArr)[] ? FlatArray<InnerArr, 0 | 1 | -1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20> : T)[]'.

Type 'FlatArray<T, 0 | 1 | -1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20>' is not assignable to type 'T extends readonly (infer InnerArr)[] ? FlatArray<InnerArr, 0 | 1 | -1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20> : T'.

Type 'T' is not assignable to type 'T extends readonly (infer InnerArr)[] ? FlatArray<InnerArr, 0 | 1 | -1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20> : T'.

Type 'DBModel' is not assignable to type 'T extends readonly (infer InnerArr)[] ? FlatArray<InnerArr, 0 | 1 | -1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20> : T'.

因此,下一步至少在DBModelCollection类中编译。注意返回类型更改为any

flat<T, D = 1 >(depth?: D): FlatArray<any, number>[] {
    return this._items;
  }

这会产生下列错误:(使用filter方法时)

TS2322: Type 'DBModelCollection<User>' is not assignable to type 'User[]'.
The types returned by 'filter(...)[Symbol.iterator]()' are incompatible between these types.
Property '[Symbol.iterator]' is missing in type 'Iterator<User, any, undefined>' but required in type 'IterableIterator<any>'.

或简单地:(使用普通赋值时)

TS2322: Type 'DBModelCollection<User>' is not assignable to type 'User[]'.

那么,回到问题上来:

  1. TypeScript如何知道它应该在我的DBModelCollection示例上调用'flat'?
    1.平面方法应该是什么样子?
    非常感谢您的帮助!
    编辑:我知道问题本身飞在面对强类型,但我开始这个项目几年前,并试图升级我的项目没有编辑约10. 000行代码..
jexiocij

jexiocij1#

好吧,我做了很多实验。我最终得到的是很多过于复杂的代码。特别是使[]索引可用导致了非常奇怪的代码。

export class DBModelCollection<T extends DBModel> implements Iterable<T> {
  [index: number | symbol]: any | T;

  private indexpointer = 0;
  _items: Array<T>;

  private indexedHandler: ProxyHandler<DBModelCollection<T>> = {
    get(target, property) {
      if (typeof property === "symbol") {
        console.log(property); /* this is where all goes wrong */
      }
      if (target.hasOwnProperty(property)) {
        return target[property]
      } else {
        return target._items[property];
      }
    },
    set(target, property, value): boolean {
      if (target.hasOwnProperty(property)) {
        target[property] = value;
      } else {
        target._items[property] = value;
      }

      return true;
    }
  };

 
  constructor(arrayLength: number = 0) {
    this._items = new Array<T>(arrayLength);
    return new Proxy(this, this.indexedHandler);
  }

我遇到的问题是,当访问任何属性或迭代器时,这是一个“捕获所有”的代理。我想要的只是让[]-indexer在数组部分工作...
此外,X11 M0 N11 X似乎与这一切相冲突。所以我不再试图让这一切工作。

相关问题