打字稿中的抽象类型数组

时间:2018-09-26 21:42:36

标签: javascript typescript

我对打字稿很陌生,正在开发的应用程序中遇到了一个问题。

export abstract class DiskElement{
    id:string;
    filename:string;
}

export class File extends DiskElement{
    size:number;
}

export class Directory extends DiskElement{
    children:DiskElement[];
}

export class User{
    shares:DiskElement[];
}

我的问题是,当我从Json文件加载用户时,它说size属性不属于DiskElement类型。

我通过将share / children声明为(File | Directory)[]来解决了我的问题,但是从长远来看,我认为这种解决方案是不可维持的。我的应用程序中有多个“父”类的数组,每当我添加新的subType时,都必须修改集合的每个声明。

我很确定有一个非常简单且不错的解决方案。

我如何加载它:

users : User =  {
    shares: 
    [
        {
           id:"{123-12312312-12312}",
           filename:"test.jpg",
           size:123123000
        },
        {
           id:"{222-2222222-22222}",
           filename:"testFolder",
           children:[{...},{...}]
         }
   ]};

它位于模拟“数据集”中,但不会与我上面解释的错误一起编译,大小不是DiskElement的属性。

将用户更改为:

export class User{
    shares:(File|Directory)[];
}

这有效,正如@Jonas Wilms指出的那样,我可以定义一个新的联合类型,即File | Directory,并确保将来在我将DiskElement子类化时更新该类型,但是我仍然觉得自己缺少一些东西

2 个答案:

答案 0 :(得分:0)

您可以将size设置为可选属性:

 export abstract class DiskElement{
    id:string;
    filename:string;
    size?: number;
 }

或者如果有多个可能的子类,例如FileBlob

export abstract class DiskElement{
   id:string;
   filename:string;
}

 class File extends DiskElement {
  size: number;
 }

 class Blob extends DiskElement {
   length: number;
 }

然后您可以使用联合类型在磁盘上键入内容:

 type Data = File | Blob;

这样,您可以在任何地方使用Data并轻松添加新类型。要访问该大小,您必须添加一个typeguard:

 var sth: Data = new File();

 if(sth instanceof File) { // sth: Data -> File
   console.log(sth.size); // works
 }

答案 1 :(得分:0)

好吧,我知道了...

在javascript中,

之间没有太大区别
var users = { prop1:"zzz", prop2:"aaaa"}; //(json without quotes)
var users = JSON.parse(json); 

结果证明在打字稿中显然不是真的。 因此,我上面的示例变为:

users : User = JSON.parse(`
{
    shares: 
    [
        {
           id:"{123-12312312-12312}",
           filename:"test.jpg",
           size:123123000
        },
        {
           id:"{222-2222222-22222}",
           filename:"testFolder",
           children:[{...},{...}]
         }
    ]
}`);

这种方式可以正常工作。