Обеспечение иерархии типов в TypeScript, даже если типы "достаточно одинаковы" - PullRequest
2 голосов
/ 26 апреля 2020

TypeScript использует «структурный подтип» для определения совместимости двух типов, что позволяет мне делать удивительную вещь, такую ​​как:

abstract class Food {
}
class Vegetable extends Food {
}
class Fruit extends Food {
    // doFruitThings() {}
}

class FruitBowl {
    addFruit(fruit: Fruit) {}
}

new FruitBowl().addFruit(new Vegetable()); // Whaaaaaat?!

TypeScript Playground Link

Обратите внимание, что приведенный выше фрагмент не выдаст ошибку компилятора, пока вы не раскомментируете метод doFruitThings() и типы не станут структурно несовместимыми.

Но - я бы предпочел , чтобы компилятор обнаружил, что мой Vegetable не является Fruit, хотя они в настоящее время имеют одни и те же свойства / функции. Я нахожусь на ранних стадиях разработки своего API и использую типы для выведения sh его перед предоставлением реализации, и меня постоянно отключают типы, которые "внезапно" становятся несовместимыми, хотя, на мой взгляд, они не были совместим для начала.

Вопрос: Есть ли способ настроить tsc на выдачу ошибки компилятора на вышеприведенной площадке?

1 Ответ

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

Конечно, вы можете использовать разные техники, даже если нет «официального» способа. Например, с брендом класса:

abstract class Food { }

class Vegetable extends Food {
    _vegetableBrand!: string;
}
class Fruit extends Food {
    _fruitBrand!: string;
    // doFruitThings() {}
}
class FruitBowl {
    addFruit(fruit: Fruit) {}
}

// error!
new FruitBowl().addFruit(new Vegetable());

Этот метод даже используется командой TS. Он не генерирует во время выполнения, но позволяет исключить структурную совместимость. brand суффикс взят из руководящих принципов TS.

Playground Link

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

...