Typescript - интерфейс, расширяющий другой интерфейс с вложенными свойствами - PullRequest
0 голосов
/ 05 декабря 2018

У меня есть такой интерфейс:

export interface Module {
  name: string;
  data: any;
  structure: {
    icon: string;
    label: string;
    ...
  }
}

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

В идеале я бы просто написал что-то вроде:

export interface DataModule extends Module {
  structure: {
    visible: boolean;
  }
}

export interface UrlModule extends Module {
  structure: {
    url: string;
  }
}

Спасибо!

1 Ответ

0 голосов
/ 05 декабря 2018

Интерфейсы не могут добавлять типы элементов в базовый интерфейс (по крайней мере, не напрямую).Вместо этого вы можете использовать тип пересечения:

export interface Module {
name: string;
data: any;
    structure: {
        icon: string;
        label: string;
    }
}

export type DataModule = Module & {
    structure: {
        visible: boolean;
    }
}

export type UrlModule = Module & {
    structure: {
        url: string;
    }
}

let urlModule: UrlModule = {
    name: "",
    data: {},
    structure: {
        icon: '',
        label: '',
        url: ''
    }
}

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

Выможет также делать это с интерфейсами, но это немного более многословно, и подразумевает использование запроса типа для получения исходного типа поля, и снова пересечение:

export interface DataModule extends Module {
    structure: Module['structure'] & {
        visible: boolean;
    }
}

export interface UrlModule extends Module {
    structure: Module['structure'] & {
        url: string;
    }
}

Действительно подробный вариант (хотя в некоторыхпроще понять), конечно, просто определить отдельный интерфейс для структуры:

export interface IModuleStructure {        
    icon: string;
    label: string;
}
export interface Module {
    name: string;
    data: any;
    structure: IModuleStructure
}
export interface IDataModuleStructure extends IModuleStructure{
    visible: boolean;
}
export interface DataModule extends Module {
    structure: IDataModuleStructure 
}
export interface IUrlModuleStructure extends IModuleStructure {
    url: string;
}
export interface UrlModule extends Module {
    structure: IUrlModuleStructure
}
let urlModule: UrlModule = {
    name: "",
    data: {},
    structure: {
        icon: '',
        label: '',
        url: ''
    }
}

Edit

Как и предполагалось pe @jcalz, мы могли бы также сделатьинтерфейс модуля универсален и передается в интерфейс соответствующей структуры:

export interface IModuleStructure {        
    icon: string;
    label: string;
}
export interface Module<T extends IModuleStructure = IModuleStructure> {
    name: string;
    data: any;
    structure: T
}
export interface IDataModuleStructure extends IModuleStructure{
    visible: boolean;
}
export interface DataModule extends Module<IDataModuleStructure> {
}
export interface IUrlModuleStructure extends IModuleStructure {
    url: string;
}
export interface UrlModule extends Module<IUrlModuleStructure> {
}
let urlModule: UrlModule = { // We could also just use Module<IUrlModuleStructure>
    name: "",
    data: {},
    structure: {
        icon: '',
        label: '',
        url: ''
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...