#typescript
#typescript
Вопрос:
У меня есть этот код для моделирования типа результата. Тип сбоя будет содержать все возможные сбои. ‘Неправильный’ не является одним из них, но я, тем не менее, могу вернуть неверный как сбой.
type Try<T, E> = Success<T> | Failures<E> | E;
// User code
type Failure = FileNotFound | NameNotFound;
class FileNotFound extends BaseFailure {}
class NameNotFound extends BaseFailure {}
class Incorrect extends BaseFailure {}
type Result<T> = Try<T, Failure>
function y() {
let x1 = x(1);
if (x1.isSuccess) {
} else {
x1.hasMany;
}
}
function x(a:number): Result<String> {
if (a>3) {
return new Success("Hallo");
} else {
return new Incorrect();
}
}
Комментарии:
1. Не могли бы вы указать все типы в коде? Некоторые из них не включены.
Ответ №1:
Typescript использует структурную совместимость для определения совместимости типов. Поэтому, когда он решает, Incorrect
совместим ли класс с Failure
, он сравнивает структуру Incorrect
с членами Failure
объединения. Делая это, он обнаружит, что он FileNotFound
имеет ту же структуру, что и Incorrect
, и, следовательно, совместим.
Чтобы обойти это, вы можете добавить элемент (предпочтительно private
) ко всем классам в объединении. Это, например, приведет к сбою:
class Success<T> { constructor(public value: T) { } isSuccess: true = true }
type Try<T, E> = Success<T> | E;
class BaseFailure {
isSuccess: false
}
type Failure = FileNotFound | NameNotFound;
class FileNotFound extends BaseFailure { private _type: "filenotfound" }
class NameNotFound extends BaseFailure { private _type: "namenotfound" }
class Incorrect extends BaseFailure { }
type Result<T> = Try<T, Failure>
function y() {
let x1 = x(1);
if (x1.isSuccess) {
} else {
}
}
function x(a: number): Result<String> {
if (a > 3) {
return new Success("Hallo");
} else {
return new Incorrect(); // error now
}
}
Вы также можете включить поле private в BaseFailure
, чтобы заставить разработчиков указывать его:
class BaseFailure<T> {
isSuccess: false
private __type: T
}
class FileNotFound extends BaseFailure<"filenotfound"> { }
class NameNotFound extends BaseFailure<"namenotfound"> { }
class Incorrect extends BaseFailure<"incorrect"> { }
Разрешение некоторой номинальной типизации уже давно обсуждалось (см. Проблему), но на данный момент это лучшее, что мы можем сделать
Комментарии:
1. Большое спасибо за ваш ответ.