Bir özyinelemeli JSON Nesnesi nasıl bir TypeScript Sınıf Nesnesine dönüştürülür?


Bir JSON nesnem var

// The data from API call
let json_data =
    [
        {
            "id": 1,
            "name": "Foo",
            "children": [
                {
                    "id": 2,
                    "name": "Foobar"
                }
            ]
        },
        {
            "id": 3,
            "name": "Bar"
        }
    ]

Ayrıca JSON formatını tanımlayan bir arayüz:

interface ICategoryTree {
    [index: number]: {
        id: number;
        name: string;
        children?: ICategoryTree;
    };
}

Bu sınıf, nesnelerin ne şekilde oluşturulması gerektiğidir:

class CategoryTree implements ICategoryTree {
    [index: number]: {
        id: number;
        name: string;
        children?: ICategoryTree;
    };

    constructor();
    constructor(data_json: ICategoryTree) {
        // todo
        // how to make an CategoryTree from an ICategoryTree-Object?
    }

    foo() {
        // fancy functionality, maybe recursive
    }
}

Başarmak istediğim şey, json_data'yı bir CategoryTree nesnesine dönüştürmek. Bunun bir yapıcı (constructor) aracılığıyla olması şart değil, ama bir yapıcı kullanmak bana doğru gibi görünüyor.

Yani böyle bir şey yapabilmek istiyorum:

// does not work for now
let ct = new CategoryTree(json_data);
ct.foo();

Arayüz özyinelemeli olduğu için sadece Object.assign kullanamıyorum. Bu yüzden, anladığım kadarıyla, bu işe yaramıyor:

Object.assign(json_data, new CategoryTree());

Cevap #1

Türleri biraz farklı bir şekilde yapılandırırdım. Bir indeks imzası tanımlamak yerine, sadece bir dizi ve bir sınıf kullanın:

interface ICategoryTree {
  id: number;
  name: string;
  children?: ICategoryTree[];
}

class CategoryTree implements ICategoryTree {
  id: number;
  name: string;
  children?: CategoryTree[];

  constructor(values: ICategoryTree) {
      this.id = values.id;
      this.name = values.name;
      this.children = values.children !== undefined ? toCategoryTreeList(values.children) : undefined;
  }

  foo() {
  }
}

function toCategoryTreeList(values: ICategoryTree[]): CategoryTree[] {
    return values.map(tree => new CategoryTree(tree));
}

Sonra onu şöyle kullanabilirsiniz:

let ct = toCategoryTreeList(json_data);
ct.foo();

toCategoryTreeList fonksiyonu, tüm üst düzey ICategoryTree öğelerini sınıf sürümüne dönüştürecek ve yapıcı (constructor) ardından tüm çocuklarını dönüştürmek için toCategoryTreeList'i özyinelemeli olarak çağıracaktır.

Ayrıca Typescript Playground'daki uygulamaya bakın.