Tìm kiếm trang web

cú pháp - Typescript - interface mở rộng interface khác với các thuộc tính lồng nhau


Tôi có một giao diện như sau:

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

Làm sao tôi có thể mở rộng nó, để tôi thêm một số thuộc tính mới vào cấu trúc, mà không phải lặp lại chính mình? Tôi có cần tạo một giao diện mới cho cấu trúc và mở rộng nó và tạo một Module mới với giao diện cấu trúc mới đó hay có cú pháp nào khác để đạt được điều này không?

Lý tưởng nhất, tôi sẽ chỉ viết một cái gì đó như:

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

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

Cảm ơn!

Câu trả lời #1

Giao diện không thể thêm vào các loại thành viên trong giao diện cơ sở (ít nhất là không trực tiếp). Bạn có thể sử dụng kiểu giao nhau thay vào đó:

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

Chúng nên hành xử giống như các interface, chúng có thể được lớp cài đặt và chúng sẽ được kiểm tra khi bạn gán các literal đối tượng cho chúng.

Bạn cũng có thể làm điều đó với các interface nhưng nó hơi dài dòng hơn, và ngụ ý việc sử dụng một truy vấn kiểu để lấy kiểu gốc của trường, và một lần nữa là giao nhau:

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

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

Lựa chọn thực sự dài dòng (mặc dù theo một số cách thì dễ hiểu hơn) tất nhiên là chỉ định nghĩa một giao diện riêng cho cấu trúc:

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

Chỉnh sửa

Theo đề xuất của @jcalz, chúng ta cũng có thể làm cho giao diện mô-đun trở nên tổng quát, và truyền vào giao diện cấu trúc phù hợp:

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

Bài viết liên quan