Typescript-接口扩展带有嵌套属性的另一个接口

时间:2018-12-05 16:32:47

标签: typescript syntax

我有一个类似的界面

public void DoWork()
{
    List<MyStruct> list;

    {  // just this
        HashSet<MyStruct> hashSet = LoadALotOfStructs();
        list = hashSet.ToList();
    }  // and this

    // Lot of code that can not use the hashSet anymore
}

如何扩展它,以便在不重复自己的情况下向结构添加一些新属性?我是否必须为结构创建一个新的接口并对其进行扩展,并使用新的结构接口创建一个新的Module,还是有其他语法可以实现此目的?

理想情况下,我会写类似这样的东西:

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

谢谢!

1 个答案:

答案 0 :(得分:1)

接口不能添加到基本接口中的成员类型(至少不是直接添加)。您可以改用交叉点类型:

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: ''
    }
}

修改

按照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: ''
    }
}