Невозможно назначить '', поскольку это свойство доступно только для чтения для статического свойства только для чтения в машинописном тексте

Рассмотрим следующий класс:

export class Foo {
  id: string;

  static readonly questionKeyPrefix: string;

  constructor(id: string, _key: string) {
    this.id = id;

    if (!Foo.questionKeyPrefix) {
      // Error: Cannot assign to 'questionKeyPrefix' because it is a read-only property
      Foo.questionKeyPrefix = _key;
    }
  }
}

Когда я пытаюсь установить questionKeyPrefix, которое является статическим свойством только для чтения, оно соответствует. Я также добавляю условие, чтобы оно было установлено только один раз!

Если убрать статику, все будет хорошо!

Есть идеи, как решить эту проблему?

Детская площадка

Почему вы хотите назначить его в конструкторе, если он статический? Это для ленивой инициализации?

kaya3 06.09.2024 12:42

В моем реальном сценарии Foo — это абстрактный базовый класс, и каждый производный класс имеет свой собственный уникальный ключ для соответствующего словаря. Чтобы упростить инициализацию, лучше было бы сделать это в конструкторе. В противном случае существует риск того, что разработчики могут забыть вызвать другие статические методы, необходимые для инициализации этого свойства.

Alireza Ahmadi 06.09.2024 12:45

@kaya3 в C# я бы использовал статический конструктор, но в машинописном тексте ничего подобного нет!

Alireza Ahmadi 06.09.2024 12:50

Но этот код не будет предоставлять разные ключи для разных подклассов, все конструкторы будут присваивать одно и то же поле базового класса.

kaya3 06.09.2024 12:59

@kaya3 Почему? Я ожидаю, что в foo1: Foo и foo2: Foo у foo1 и foo2 разные ключи. Я ошибаюсь?

Alireza Ahmadi 06.09.2024 13:01

Как разные экземпляры могут иметь разные ключи, если это статическое свойство?

kaya3 06.09.2024 13:02

@kaya3 Вы правы, похоже, моя проблема сложнее, чем я думал. Вероятно, мне нужно добавить это статическое свойство в каждый подкласс. Но это также требует огромного рефакторинга, поскольку у меня большое приложение.

Alireza Ahmadi 06.09.2024 13:05

Или вы можете просто сделать это свойством экземпляра. Или, если вас беспокоит добавление дополнительных полей к каждому объекту, сделайте это методом с помощью get.

kaya3 06.09.2024 13:07

@kaya3 На самом деле мне нужно быть статичным для каждого подкласса

Alireza Ahmadi 06.09.2024 13:07
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
9
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В TS вы можете использовать статические блоки для инициализации статических членов.

abstract class Foo {
    id: string;

    static questionKeyPrefix: string = "";

    constructor(id: string, _key: string) {
      this.id = id;    
    }
}

class Bar extends Foo {
    static {
      Foo.questionKeyPrefix += "abc";
    }
}

console.info(Foo.questionKeyPrefix);

К сожалению, вы Не можете назначить статику только для чтения в статических блоках #56584

Спасибо за ответ!

Alireza Ahmadi 06.09.2024 14:17
Ответ принят как подходящий

То, как ваш код спроектирован на данный момент, не может работать, потому что у вас есть статическое свойство, значение которого может меняться каждый раз при вызове конструктора. Таким свойством быть не может readonly, поскольку можно наблюдать изменение его значения после инициализации.

Однако из комментариев кажется, что на самом деле это не моделирует то, чего вы пытаетесь достичь, потому что вы хотите, чтобы это свойство имело разное значение для каждого подкласса, а не другое значение для каждого экземпляра.


Самое простое решение — сделать его свойством экземпляра и просто присвоить этому свойству экземпляра соответствующее значение на основе его подкласса. Свойство экземпляра не обязательно должно быть параметром конструктора для каждого подкласса; вы можете передать его из конструктора подкласса:

class Base {
    // instance field
    readonly key: string;
    constructor(_key: string) {
        this.key = _key;
    }
}

class Foo extends Base {
    constructor() {
        super('Foo');
    }
}

class Bar extends Base {
    constructor() {
        super('Bar');
    }
}

Ссылка на игровую площадку

Альтернативный вариант, если вас беспокоит, что это свойство (например, потому что оно отображается при сериализации объекта), — сделать это «виртуальным» свойством с помощью get:

abstract class Base {
    abstract readonly key: string;
}

class Foo extends Base {
    get key() {
        return 'Foo';
    }
}

class Bar extends Base {
    get key() {
        return 'Bar';
    }
}

Ссылка на игровую площадку

Поскольку геттер объявляется для каждого подкласса, значение указывается для каждого подкласса, а не для каждого экземпляра.


Вообще говоря, «статика для каждого подкласса» не очень полезна, поскольку к статическим свойствам обычно не осуществляется полиморфный доступ. Это имело бы смысл только в том случае, если бы сами классы передавались как значения, например.

interface KeyedClass {
    readonly key: string;
}

class Foo {
    static readonly key = 'Foo';
}

class Bar {
    static readonly key = 'Bar';
}

function logKey(cls: KeyedClass) {
    console.info(cls.key);
}

logKey(Foo);
logKey(Bar);

Ссылка на игровую площадку

Если вы этого не делаете, то нет смысла делать что-то «статическим для каждого класса», потому что вы не можете получить к нему полиморфный доступ из контекста экземпляра. this.key не будет работать и Base.key не является полиморфным; вы просто получите значение статического свойства базового класса, независимо от того, к какому подклассу принадлежит this.

Спасибо за ответ!

Alireza Ahmadi 06.09.2024 14:17

Другие вопросы по теме