Наследование Typescript расширяет свойства - PullRequest
1 голос
/ 07 апреля 2020

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

Пользователь определяется как


export type userDoc = {
  firstname: string
  lastname: string
  email: string
}

export class User {
  props: userDoc = {
      firstname: "",
      lastname: "",
      email: "", 
      {...}
  }
}

А участник (наследующий от пользователя) как

type participantDoc = {
    pseudonym: string
    karma: number
    impact: number
    level: number
    experience: number
  }

export class Participant extends User {
    props: participantDoc = {
      pseudonym: "",
      karma: 0,
      impact: 0,
      level: 0,
      experience: 0
    }
}

Теперь я надеюсь достичь расширения атрибутов родительского класса в дочернем классе. Я работаю с реквизитом из-за mongodb и потому, что безопаснее назначать его таким образом вместо Object.assign ().

Набирает текст ошибки:

TS2416: Property 'props' in type 'Participant' is not assignable to thesame property in base type 'User'.
  Type 'participantDoc' is missing the following properties from type 'userDoc': firstname, lastname, email, and 6 more.

Ответы [ 2 ]

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

Вам придется расширять типы реквизита так же, как вы делали это для класса.

Изменить

export type participantDoc = {
    pseudonym: string
    karma: number
    impact: number
    level: number
    experience: number
}

на

export type participantDoc = {
    pseudonym: string
    karma: number
    impact: number
    level: number
    experience: number
} & userDoc

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

export interface userDoc {
  firstname: string
  lastname: string
  email: string
}

export interface participantDoc extends userDoc {
    pseudonym: string
    karma: number
    impact: number
    level: number
    experience: number
}
0 голосов
/ 08 апреля 2020

Наследование может работать между User и Participant классами, если User является родовым c для указания типа его поля props.

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

const emptyUserProps = {
    firstname: "",
    lastname: "",
    email: "", 
};

export type UserProps = typeof emptyUserProps;

export class User<TProps extends UserProps = UserProps> {
    props = emptyUserProps as TProps; // Type assertion `as TProps` is needed here in order to initialise the field using `emptyUserProps` (of type `UserProps`, not `TProps`)
}

// -------

const emptyParticipantProps = {
    pseudonym: "",
    karma: 0,
    impact: 0,
    level: 0,
    experience: 0,
};

export type ParticipantProps = typeof emptyParticipantProps;

export class Participant extends User<UserProps & ParticipantProps> {
    props = {
        ...emptyUserProps,
        ...emptyParticipantProps,
    };
}

Но если User и Participant совместно используют только некоторые данные в поле props, безопаснее достичь полиморфизма, используя базовый интерфейс, а не наследование классов:

export interface WithProps<TProps> {
    props: TProps;
}

// ----

const emptyUserProps = {
    firstname: "",
    lastname: "",
    email: "", 
};

export type UserProps = typeof emptyUserProps;

export class User implements WithProps<UserProps> {
    props = emptyUserProps;
}

// -------

const emptyParticipantProps = {
    pseudonym: "",
    karma: 0,
    impact: 0,
    level: 0,
    experience: 0,
};

export type ParticipantProps = typeof emptyParticipantProps;

export class Participant implements WithProps<UserProps & ParticipantProps> {
    props = {
        ...emptyUserProps,
        ...emptyParticipantProps,
    };
}

Другой вариант - использовать один класс generi c с несколькими фабричными методами stati c, один для создания пользователя "basi c", другой для участника:

const emptyUserProps = {
    firstname: "",
    lastname: "",
    email: "", 
};

const emptyParticipantProps = {
    pseudonym: "",
    karma: 0,
    impact: 0,
    level: 0,
    experience: 0,
};

export class User<TProps> {
    // `TProps` inferred to `typeof emptyUserProps`
    static createUser(props = emptyUserProps) {
        return new User(props);
    }

    // `TProps` inferred to `(typeof emptyUserProps) & (typeof emptyParticipantProps)`
    static createParticipant(props = {
        ...emptyUserProps,
        ...emptyParticipantProps,
    }) {
        return new User(props);
    }

    private constructor(public props: TProps) {}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...