Переписывающий Typescript абстрактный метод, возвращающий void - PullRequest
3 голосов
/ 17 апреля 2020
abstract class Base{
    abstract sayHello(): void;
}

class Child extends Base{
    sayHello() {
        return 123;
    }
}

Тип возврата абстрактного метода - void , но я могу реализовать его с помощью возврата числового типа. Я не взял никакой ошибки от компилятора. Это ошибка в Typescript?

TS Spe c

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

Ответы [ 2 ]

2 голосов
/ 17 апреля 2020

Причина этого в том, что система типов в машинописи работает над структурной системой типов. Идея типов в некотором роде похожа на «контракты», где правила устанавливают, что определенные типы совместимы с определенными типами. Компилятор выдаст ошибку только в случае разрыва контракта. Так, например:

abstract class Base{
    abstract sayHello(): void;
}

class Child extends Base{
    sayHello(): number {
        return 123;
    }
}

Это работает, потому что, хотя наш метод возвращает число, когда мы реализуем все, что использует sayHello() и ожидает, что он возвратит пустоту, не будет иметь побочных эффектов, контракты не нарушаются , Это просто потому, что Microsft установил правило в машинописи, говоря, что возвращаемый тип void совместим с типом возвращаемого числа. Причина в том, что, как я уже говорил, у него нет побочных эффектов, все, что ожидает от sayHello() возврата void, должно работать должным образом.

С другой стороны, если бы я сделал что-то вроде этого:

abstract class Base{
    abstract sayHello(): number;
}

class Child extends Base{
    sayHello(): void {
        return;
    }
}

Это приведет к ошибке, потому что теперь все, что использует sayHello() и ожидает, что оно будет числом, будет затронуто, контракт типов нарушен из-за ошибки компилятора.

Вы можете посмотреть на это как особенность гибкости в системе типов при обмене на случайную эквивалентность типов.

На языке, подобном C#, в котором используется система именных типов, это не позволит нам иметь абстрактный метод void, который при реализации возвращает строку, так как фокусируется на эквивалентности типов, типы должны быть то же самое для совместимости друг с другом.

Надеюсь, это поможет!

Система структурного типа: https://en.wikipedia.org/wiki/Structural_type_system

Система номинального типа: https://en.wikipedia.org/wiki/Nominal_type_system

Совместимость типов машинописного текста: https://www.typescriptlang.org/docs/handbook/type-compatibility.html

Spe c: https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3114 -направленность-совместимость

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

I цитата Райан Кавано, ведущий разработчик TS:

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

Таким образом, речь идет о типе функции, которая возвращает void, может принимать (быть назначенным) значение функции, которая возвращает что-либо.

type ReturnVoid = () => void

const foo: ReturnVoid = () => 42  // all good

Это поведение описано в Совместимость назначений раздел

M - это неспециализированный вызов или сигнатура конструкции, а S имеет очевидный вызов или создайте сигнатуру N, где [...] тип результата M равен Void , или тип результата N можно присвоить типу результата M

Ссылки:

  1. https://github.com/Microsoft/TypeScript/wiki/FAQ#why - функции, возвращающие функции, не пустые, присваиваемые функции, возвращающие пустоту
  2. https://github.com/microsoft/TypeScript/issues/21674
...