Исправьте типы TypeScript для расширенного параметра конструктора в производном классе - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть класс Base с параметром конструктора BaseParams, и я хочу расширить класс Derived с Base, который принимает параметр конструктора ExtendedParams и передает его в super() вдоль с некоторыми значениями по умолчанию. Проблема в том, что я не могу найти правильную комбинацию модификаторов доступа и типов для параметра конструктора Derived.

Вот что у меня есть:

interface BaseParams {
  first: string;
}

interface ExtendedParams extends BaseParams {
  last?: string;
}

class Base {
  constructor(protected params: BaseParams) {}
  inspect(): void {
    console.log(this.params);
  }
}

class Derived extends Base {
  constructor(??? params ???) {
    super({ first: 'John', last: 'default', ...params });  // override default params with specified ones
    this.params.last;  // #1 - this should not generate any compile errors
    this.params.whatever = 'Wrong';  // #2 - TS should flag this as not existing on type ExtendedParams
  }
}

const d = new Derived({ first: 'Mike' });
d.inspect();  // #3 - should output { first: 'Mike', last: 'default', whatever: 'Wrong' }

I попытался объявить Derived params как protected. Это решает # 1 и # 2.

class Derived extends Base {
  constructor(protected params: ExtendedParams) {
    super({ first: 'John', last: 'default', ...params });
    this.params.last;  // #1 - ok, no error
    this.params.whatever = 'Wrong';  // #2 - ok, flagged: `whatever` doesn't exist on type ExtendedParams
  }
}

Проблема в том, что назначение last: 'default' не выполняется, потому что protected генерирует назначение this.params = params, которое перезаписывает значение params, переданное в super(), поэтому d.inspect() выводит только { first: 'Mike', whatever: 'Wrong' }.

Я попытался опустить модификатор доступа для params. Это приводит к правильному выводу { first: 'Mike', last: 'default', whatever: 'Wrong' }, но также к тому, что this.params.last помечается как ошибка, does not exist on type 'BaseParams'.

class Derived extends Base {
  constructor(params: ExtendedParams) {
    super({ first: 'John', last: 'default', ...params });
    this.params.last;  // #1 - wrong ly flagged 
    this.params.whatever = 'Wrong';  // #2 - ok, flagged
  }
}

Есть ли какие-то магические ошибки TypeScript c, чтобы сообщить компилятору, что в Derived class, this.params имеет тип ExtendedParams, и , значения по умолчанию передаются на вызов super(), и this.params впоследствии не перезаписывается?

1 Ответ

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

Но из Derived вы получаете доступ к Base.params, который четко обозначен как BaseParams.

Если вы хотите, чтобы свойство params изменило тип в производных классах, вам понадобится универсальный c базовый тип:

// <P = BaseParams> allows to instantiate Base with BaseParams as default type.
class Base<P = BaseParams> {
    constructor(protected params: P) {}
    /* ... */
}

class Derived extends Base<ExtendedParams> {
    constructor(params: ExtendedParams) {
        super({ first: 'John', last: 'default', ...params });  // override default params with specified ones
        this.params.last;                // OK
        this.params.whatever = 'Wrong';  // Wrong
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...