简体   繁体   中英

Using TypeScript Generic Interfaces

I have several types of objects, like articles, divisions, profiles, etc. I defined an interface for each, basically:

interface IArticle {
    title: string;
    body: string;
}

interface IProfile {
    name: string;
    email: string;
}

interface IDivision {
    name: string;
    leader: IProfile;
}

Now I want to, in some cases, be able to add a formTitle property when using these on a page that displays a form. I thought I could do something like this:

// Failed
interface IForm<T> {
    formTitle: string;
}

function formDisplay(resource: IForm<IProfile>) { }

But when I do that, I get an error indicating the object properties ( name and email , in this case) do not exist on type IForm<IProfile> . So I guess this is not the correct use of generics. Coming from Ruby and JavaScript, I'm still new to the whole static typing thing.

To get around this, I have been writing separate interfaces for each object, like this:

// Not reusable
interface IArticleForm extends IArticle {
    formTitle: string;
}

Another alternative I could think of would be to add an optional property to a base interface and then extend the regular object interfaces from there.

// Does not provide helpful type checking
interface IBase {
    formTitle?: string;
}
interface IArticle extends IBase { }

But I want formTitle to be required on these form pages so that I don't forget to set it. Is there some way to apply a group of required properties to multiple objects in a reusable way?

Looks like you are looking for Intersection Types. this allows you to mix to behaviors together. You can even alias the newly created type to give it a convenient name that describes its usage.

For your example use:

interface IProfile {
    name: string;
    email: string;
}
interface IForm {
    formTitle: string;
}
type IProfileForm = IForm & IProfile;

function formDisplay(resource: IProfileForm) { }

Generics are intended to "contain" whatever type is generic - you need a field in your IForm that is of your generic type:

interface IMyContent {}

interface IProfile extends IMyContent {
    name: string;
    email: string;
}

interface IForm<T extends IMyContent> {
    formTitle: string;
    content: T;
}

var x : IForm<IProfile> = {
    formTitle: "",
    content: {name: "", email: ""}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM