虽然应该标记类型,但仍会编译打字稿代码

时间:2019-03-07 10:08:57

标签: 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 个答案:

答案 0 :(得分:1)

Typescript使用结构兼容性来确定类型兼容性。因此,当确定类Incorrect是否与Failure兼容时,就将Incorrect的结构与Failure并集的成员进行比较。这样做会发现FileNotFoundIncorrect具有相同的结构,因此是兼容的。

要解决此问题,您可以将一个成员(最好是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
    }
}

您还可以在BaseFailure中包含私有字段,以强制实施者指定它:

class BaseFailure<T> {
    isSuccess: false
    private __type: T
}


class FileNotFound extends BaseFailure<"filenotfound"> { }
class NameNotFound extends BaseFailure<"namenotfound"> { }

class Incorrect extends BaseFailure<"incorrect"> { }

长期以来,已经讨论了允许一些名义上的键入(请参阅issue),但是目前这是我们所能做的最好的事情