У меня есть интерфейс с более чем 200 свойствами. Как класс может реализовать этот интерфейс, не объявляя все 200 снова?

#typescript #inheritance #static-typing

#typescript #наследование #статическая типизация

Вопрос:

У меня есть интерфейс с более чем 200 свойствами и класс, который использует эти же свойства.

 interface MyProperties {
  property1: string
  property2: string
  ...
  property232: string
}

class MyClass {
  constructor() {
    this.property1 = 'foo';
    this.property2 = 'bar';
    ...
    this.property232 = 'bar';
  }
}
 

Прямо сейчас typescript выдаст мне эту ошибку: Property 'property1' does not exist on type 'MyClass'.

Есть ли способ сообщить typescript, что свойства моего класса поступают из MyProperties интерфейса?

Я не хочу делать что-то подобное:

 class MyClass {
  property1: string
  property2: string
  
  constructor() {
    this.property1 = 'foo';
    this.property2 = 'bar';
  }
}
 

поскольку интерфейс уже широко используется в моем коде, и я не хочу повторять эти типизации.

Ближе всего я подошел к этому

 class MyClass {
  property1: MyProperties['property1'];
  property2: MyProperties['property2'];
  ...
  property232: MyProperties['property232'];

  constructor() {
    this.property1 = 'foo';
    this.property2 = 'bar';
    ...
    this.property232 = 'bar';
  }
}
 

но это не очень красиво, поскольку в моем реальном коде у меня более 200 свойств

Комментарии:

1. Два предоставленных ответа решают вашу проблему, за исключением того, что вы говорите, что они не работают для вас, потому что у вас более 200 свойств. Затем вам нужно сделать «200 свойств» в центре вашего вопроса, а не в виде крошечного комментария в конце. Я переместу его наверх, но вам нужно добавить больше информации.

2. Например, вам нужно предоставить больше информации об этих более чем 200 свойствах: все ли они находятся в одном интерфейсе? При таком количестве свойств имеет ли смысл статическая проверка типов? Вы должны предоставить значения для всех из них (если они не являются необязательными), чтобы у вас все еще была «не очень красивая» проблема. Если вы предоставите подробную информацию о своих потребностях, а не «заставите этот код работать», мы можем предложить лучшие решения.

3. Нет, это не то, как интерфейсы работают в Typescript или ЛЮБОМ другом языке, который я знаю. Вы не наследуете интерфейсы, вы их реализуете , а «реализовать» означает, что вам нужно делать то, что вы не хотите делать. Вы можете превратить свой интерфейс в абстрактный класс, а затем использовать наследование… И, ПОЖАЛУЙСТА, ответьте на другие мои вопросы, либо здесь, в комментариях, либо обновив свой вопрос (лучше).

4. @Inigo Они все в одном интерфейсе и представляют собой смесь всевозможных типов. Для любого другого типа данных я могу просто сделать const myObject: MyType = {} . Из ответов здесь я предполагаю, что для классов нет эквивалента.

5. Что такое MyType ? Вы не можете этого сделать const myObject: MyProperties = {} . Вы не можете соответствовать типу, фактически не реализуя все необязательные поля этого типа, если вы не используете наследование. Не стесняйтесь поправлять меня примером в Typescrtipt Playground, например, вот так , и, пожалуйста, укажите в своем вопросе. Вам нужно больше работать с ясностью, а не нам. Моя интуиция говорит, что вы в замешательстве. Спасибо.

Ответ №1:

Ну, просто добавьте implements MyProperties предложение в класс:

 interface MyProperties {
    property1: string
    property2: string
}

class MyClass implements MyProperties {
    property1: string;
    property2: string;

    constructor() {
        this.property1 = 'foo';
        this.property2 = 'bar';
    }
}
 

Комментарии:

1. Тогда мне все равно нужно вручную добавить все мои типы в класс. У меня есть интерфейс с более чем 200 методами, поэтому я бы предпочел не вводить все это дважды

2. Если это методы, вам, конечно, нужно будет реализовать их самостоятельно в любом случае? Может быть, вам нужен абстрактный класс?

3. Я согласен, что вам, вероятно, нужен абстрактный класс, а не интерфейс

4. Тип с более чем 200 свойствами пахнет для меня очень подозрительно. Бьюсь об заклад, что если бы мы знали о лежащей в основе проблеме, мы бы порекомендовали что-то совершенно другое.

Ответ №2:

Прямо сейчас typescript выдаст мне эту ошибку

Это потому, что в классе нет определения для этих свойств. Вы должны сообщить компилятору TypeScript, который MyClass обладает этими свойствами:

 class MyClass {
    property1: string;
    property2: string;
    constructor() {
        this.property1 = 'foo';
        this.property2 = 'bar';
    }
}
 

Теперь компилятор знает, какие свойства MyClass имеет, и может реализовать этот MyClass реализующий MyProperties интерфейс:

 interface MyProperties {
    property1: string
    property2: string
}

class MyClass {
    property1: string;
    property2: string;
    constructor() {
        this.property1 = 'foo';
        this.property2 = 'bar';
    }
}

const a: MyProperties = new MyClass(); // no error here
 

Также вы можете явно реализовать MyProperties интерфейс для улучшения читаемости кода с помощью implements MyProperties :

 interface MyProperties {
    property1: string
    property2: string
}

class MyClass implements MyProperties {
    property1: string;
    property2: string;
    constructor() {
        this.property1 = 'foo';
        this.property2 = 'bar';
    }
}

const a: MyProperties = new MyClass(); // no error here too
 

Комментарии:

1. но в этом случае мне все равно придется вводить каждое свойство дважды, что не идеально для поддержания. У меня в моем классе более 200 свойств.