Как я могу сузить тип свойства readonly производного класса? - PullRequest
2 голосов
/ 22 июня 2019

Я хочу расширить Uint8Array таким классом, который ограничивает тип определенной длиной. Например:

class Bytes32 extends ByteArray {
    constructor() { super(32) }
    length: 32 = 32
}

Однако, когда я пытаюсь создать экземпляр этого класса, я получаю сообщение об ошибке, потому что свойство length в Uint8Array имеет только геттер:

TypeError: Cannot set property length of [object Object] which has only a getter

Если я не выполняю присваивание в объявлении класса, а вместо этого выполняю только length: 32, тогда я получаю ошибку компилятора о том, что length никогда не присваивается.

Можно ли как-то сказать TypeScript (либо путем утверждения посредством доказательства), что свойство length этого класса будет всегда быть 32 и, следовательно, его тип должен быть сужен до 32 с number?

Я специально хочу, чтобы компилятор знал о сужении, чтобы у меня была функция с такой сигнатурой:

function apple(data: ArrayLike<number> & { length: 32 })

Такая подпись улучшит проверку типов в моем проекте, без тесной связи с каким-либо конкретным контейнером массива чисел. Единственное требование состоит в том, чтобы вещь, которую они мне дают, должна (предположительно, компилятором) иметь ровно 32 элемента.

1 Ответ

2 голосов
/ 23 июня 2019

Поскольку вы просто хотите уточнить тип элемента length, в частности, от number до 32, и только инициализируете его для проверки типа и, таким образом, вносите ошибку времени выполнения, мы можем решить эту проблему следующим образом:используя объявление слияния .

В частности, мы можем уточнить typeof от length до 32, введя интерфейс, который объявляет свойство и объединяется с самим классом.

Следующее делает хитрость

interface Bytes32 {
  readonly length: 32;
}

class Bytes32 extends Uint8Array {
  constructor() { super(32); }
}

Этот метод имеет широкий спектр применения, но также должен использоваться с осторожностью.

...