Может ли свойство объекта, описанного в интерфейсе TypeScript, реализовать сам интерфейс внутри своего объявления? - PullRequest
0 голосов
/ 21 апреля 2020

Я знаю, что это, вероятно, странный запрос, но в моем случае он идеально подошел бы.

У меня есть объект с именем layer, который может выглядеть примерно так:

const layer = {
    Title: 'parent title',
    Name: 'parent name',
    Layer: {
        Title: 'child title'
    }
}

У него есть свойство Title, которое является обязательным, и свойства Name и Layer, которые являются необязательными.

В случае наличия свойства Layer оно имеет те же характеристики, что и были описаны (таким образом, , он может иметь другие вложенные Layer s).

Мне нужно определить для него интерфейс , и я подумал, что что-то вроде этого может работать:

interface LayerInterface {
    Title: string;
    Name?: string;
    Layer?: LayerInterface;
}

Мой вопрос заключается в том, могу ли я использовать LayerInterface в качестве типа свойства Layer, которое определено в самом LayerInterface.

Я просто cur ios, если это можно сделать так или иначе простой способ.

1 Ответ

1 голос
/ 21 апреля 2020

Да, ваше рекурсивное определение интерфейса:

interface LayerInterface {
    Title: string;
    Name?: string;
    Layer?: LayerInterface;
}

успешно компилируется и означает, что вы хотите, чтобы это означало:

function processLayer(layer: LayerInterface) {}

processLayer(layer); // okay

const badLayer = { Title: "", Name: "", Layer: { Title: 123, Name: false } }
processLayer(badLayer); // error!
// --------> ~~~~~~~~
/* Argument of type
  '{ Title: string; Name: string; Layer: { Title: number; Name: boolean; }; }' 
  is not assignable to parameter of type 'LayerInterface'. 
*/

Вы видите, как badLayer не соответствует LayerInterface из-за свойств Title и Name вложенного объекта Layer имеют неправильный тип.


Обратите внимание, что это вовсе не странный запрос; многие обычно используемые интерфейсы и классы работают таким образом, по крайней мере, до некоторой степени. Любая древовидная структура, такая как DOM , будет иметь определение типа, где некоторые из его свойств и методов содержат некоторую ссылку на определяемый тип.

Узел DOM Element имеет свойство children, представляющее массив в виде массива Element узлов , позволяющий вам написание рекурсивных функций обработки элементов:

function processElement(elem: Element) {
    console.log(elem.nodeName);
    for (let i = 0; i < elem.children.length; i++) {
        processElement(elem.children[i]);
    }
}

Что касается документации:

Похоже, что "официальная" документация говорит, что вы можете сделать это для интерфейсов ( устарел) TypeScript Spe c:

Классы и интерфейсы могут ссылаться на себя во внутренней структуре, создавая рекурсивные типы с бесконечной вложенностью. Например, тип

interface A { next: A; }

содержит бесконечно вложенную последовательность свойств 'next'.

Он также работает в псевдонимах типов, как упомянуто в разделе справочника для псевдонимов типов :

У нас также может быть псевдоним типа, ссылающийся на себя в свойстве:

type Tree<T> = {
   value: T;
   left: Tree<T>;
   right: Tree<T>;
}

Хорошо, надеюсь, это поможет ; удачи!

Детская площадка ссылка на код

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...