打字稿使用Observable.of区分联合类型

lam*_*utz 5 discriminated-union observable rxjs typescript

我正在尝试将Typescript 2.0的已区分联合类型与RxJS一起使用,但是却收到一个错误,即我返回的对象不是联合类型的类型之一。

这是我的类型:

interface Square {
  kind: "square";
  width: number;
}

interface Circle {
  kind: "circle";
  radius: number;
}

interface Center {
  kind: "center";
}

type Shape = Square | Circle | Center;
Run Code Online (Sandbox Code Playgroud)

我只返回一个Shape不使用Observable编译器的函数完全可以:

function shapeFactory(width: number): Shape {
  if (width > 5) {
    return {kind: "circle", radius: width};
  } else if (width < 2) {
    return {kind: "square", width: 3};
  }

  return {kind: "center"};
}
Run Code Online (Sandbox Code Playgroud)

当我改为尝试返回Observable<Shape>类似的内容时:

function shapeFactoryAsync(width: number): Observable<Shape> {
  if (width > 5) {
    return Observable.of({kind: "circle", radius: width});
  } else {
    return Observable.of({kind: "center"});
  }
}
Run Code Online (Sandbox Code Playgroud)

我遇到编译错误:

Type 'Observable<{ kind: string; radius: number; }>' is not assignable to type 'Observable<Shape>'.
  Type '{ kind: string; radius: number; }' is not assignable to type 'Shape'.
    Type '{ kind: string; radius: number; }' is not assignable to type 'Center'.
      Types of property 'kind' are incompatible.
        Type 'string' is not assignable to type '"center"'.
Run Code Online (Sandbox Code Playgroud)

我希望我的第一个返回值是类型Observable<{ kind: "circle"; radius: number; }>,因为这kind是所有Shape类型的区别。奇怪的是,这还可以Observable.of({kind: "center"}),可能是因为没有其他数据与之相关?

如果我明确分配了该对象并为该分配指定了类似的类型,则可以修复该问题:

let circle: Circle = {kind: "circle", radius: width};
return Observable.of(circle);
Run Code Online (Sandbox Code Playgroud)

尽管这似乎应该是不必要的强制转换。

我只是在做这件事完全错误,还是为了确定kind应该是值"circle"而不是类型而必须进行强制转换string

car*_*ant 4

对于像这样的调用Observable.of({ kind: "center" }),TypeScript 无法从匿名参数推断类型。

您可以通过在调用泛型方法时指定类型变量来解决您的问题Shapeof

function shapeFactoryAsync(width: number): Observable<Shape> {
  if (width > 5) {
    return Observable.of<Shape>({ kind: "circle", radius: width });
  } else {
    return Observable.of<Shape>({ kind: "center" });
  }
}
Run Code Online (Sandbox Code Playgroud)

指定类型变量后,TypeScript 不再需要推断类型。