title: mat-tree angular material custom
body: <hr>
  
  <p>Home.component.html</p>
  
  <hr>
  
  <pre><code>    &lt;mat-tree [dataSource]="dataSource" [treeControl]="treeControl"&gt;
    &lt;mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle matTreeNodePadding&gt;
      &lt;button mat-icon-button disabled&gt;&lt;/button&gt;
      &lt;mat-icon class="type-icon" [attr.aria-label]="node.type + 'icon'"&gt;
        {{ node.type ==='file' ? 'description' : 'folder' }}
      &lt;/mat-icon&gt;
      {{node.name}}
    &lt;/mat-tree-node&gt;
  
    &lt;mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding&gt;
      &lt;button mat-icon-button matTreeNodeToggle
              [attr.aria-label]="'toggle ' + node.name"&gt;
        &lt;mat-icon class="mat-icon-rtl-mirror"&gt;
          {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
        &lt;/mat-icon&gt;
      &lt;/button&gt;
      &lt;mat-icon class="type-icon" [attr.aria-label]="node.type + 'icon'"&gt;
        {{ node.type ==='file' ? 'description' : 'folder' }}
      &lt;/mat-icon&gt;
      {{node.name}}
    &lt;/mat-tree-node&gt;
  &lt;/mat-tree&gt;
  </code></pre>
  
  <hr>
  
  <p>Home.component.ts</p>
  
  <hr>
  
  <pre><code>   import { Component } from '@angular/core';
  import { MatTreeFlatDataSource, MatTreeFlattener } from '@angular/material/tree';
  import { of as observableOf } from 'rxjs';
  import { FlatTreeControl } from '@angular/cdk/tree';
  // import { files } from './example-data';
  
  /** File node data with nested structure. */
  export interface FileNode {
    name: string;
    type: string;
    children?: FileNode[];
  }
  
  /** Flat node with expandable and level information */
  export interface TreeNode {
    name: string;
    type: string;
    level: number;
    expandable: boolean;
  }
  
  export const files = [
    {
      name: 'material2',
      type: 'folder',
      children: [
        {
          name: 'src',
          type: 'folder',
          children: [
            {
              name: 'cdk',
              children: [
                { name: 'package.json', type: 'file' },
                { name: 'BUILD.bazel', type: 'file' },
              ]
            },
            { name: 'lib', type: 'folder' }
          ]
        }
      ]
    },
    {
      name: 'angular',
      type: 'folder',
      children: [
        {
          name: 'packages',
          type: 'folder',
          children: [
            { name: '.travis.yml', type: 'file' },
            { name: 'firebase.json', type: 'file' }
          ]
        },
        { name: 'package.json', type: 'file' }
      ]
    },
    {
      name: 'angularjs',
      type: 'folder',
      children: [
        { name: 'gulpfile.js', type: 'file' },
        { name: 'README.md', type: 'file' }
      ]
    }
  ];
  
  
  @Component({
    selector: 'my-app',
    templateUrl: './app.component.html',
    styleUrls: [ './app.component.css' ]
  })
  export class AppComponent {
  
    /** The TreeControl controls the expand/collapse state of tree nodes.  */
    treeControl: FlatTreeControl&lt;TreeNode&gt;;
  
    /** The TreeFlattener is used to generate the flat list of items from hierarchical data. */
    treeFlattener: MatTreeFlattener&lt;FileNode, TreeNode&gt;;
  
    /** The MatTreeFlatDataSource connects the control and flattener to provide data. */
    dataSource: MatTreeFlatDataSource&lt;FileNode, TreeNode&gt;;
  
    constructor() {
      this.treeFlattener = new MatTreeFlattener(
        this.transformer,
        this.getLevel,
        this.isExpandable,
        this.getChildren);
  
      this.treeControl = new FlatTreeControl&lt;TreeNode&gt;(this.getLevel, this.isExpandable);
      this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
      this.dataSource.data = files;
    }
  
    /** Transform the data to something the tree can read. */
    transformer(node: FileNode, level: number) {
      return {
        name: node.name,
        type: node.type,
        level: level,
        expandable: !!node.children
      };
    }
  
   /** Get the level of the node */
    getLevel(node: TreeNode) {
      return node.level;
    }
  
    /** Return whether the node is expanded or not. */
    isExpandable(node: TreeNode) {
      return node.expandable;
    };
  
    /** Get the children for the node. */
    getChildren(node: FileNode) {
      return observableOf(node.children);
    }
  
    /** Get whether the node has children or not. */
    hasChild(index: number, node: TreeNode){
      return node.expandable;
    }
  
  }
  </code></pre>
  
  <hr>
  
  <p>ERROR in src/app/modules/home/home.component.ts(349,5): error TS2322: Type '({ name: string; type: string; children: { name: string; type: string; children: ({ name: string; children: { name: string; type: string; }[]; type?: undefined; } | { name: string; type: string; children?: undefined; })[]; }[]; } | { ...; })[]' is not assignable to type 'FileNode[]'.
    Type '{ name: string; type: string; children: { name: string; type: string; children: ({ name: string; children: { name: string; type: string; }[]; type?: undefined; } | { name: string; type: string; children?: undefined; })[]; }[]; } | { ...; }' is not assignable to type 'FileNode'.
      Type '{ name: string; type: string; children: { name: string; type: string; children: ({ name: string; children: { name: string; type: string; }[]; type?: undefined; } | { name: string; type: string; children?: undefined; })[]; }[]; }' is not assignable to type 'FileNode'.
        Types of property 'children' are incompatible.
          Type '{ name: string; type: string; children: ({ name: string; children: { name: string; type: string; }[]; type?: undefined; } | { name: string; type: string; children?: undefined; })[]; }[]' is not assignable to type 'FileNode[]'.
            Type '{ name: string; type: string; children: ({ name: string; children: { name: string; type: string; }[]; type?: undefined; } | { name: string; type: string; children?:undefined; })[]; }' is not assignable to type 'FileNode'.
              Types of property 'children' are incompatible.
                Type '({ name: string; children: { name: string; type: string; }[]; type?: undefined; } | { name: string; type: string; children?: undefined; })[]' is not assignable to type 'FileNode[]'.
                  Type '{ name: string; children: { name: string; type: string; }[]; type?: undefined; } | { name: string; type: string; children?: undefined; }' is not assignable totype 'FileNode'.
                    Type '{ name: string; children: { name: string; type: string; }[]; type?: undefined; }' is not assignable to type 'FileNode'.</p>
  
  <h2>                    Property 'type' is optional in type '{ name: string; children: { name: string; type: string; }[]; type?: undefined; }' but required in type 'FileNode'.</h2>