Typescript使用Observable.of区分联合类型

时间:2017-01-03 23:34:57

标签: typescript rxjs observable discriminated-union

我试图使用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;

此函数我只返回一个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"};
}

当我尝试像这样返回Observable<Shape>时:

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

我遇到了编译错误:

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"'.

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

如果我明确地分配了对象并为赋值赋予类似的类型,我能够修复它:

let circle: Circle = {kind: "circle", radius: width};
return Observable.of(circle);

虽然这看起来应该是不必要的演员。

我只是这样做完全错了,或者为了弄明kind应该是"circle"而不是类型string而需要投射?

1 个答案:

答案 0 :(得分:3)

通过Observable.of({ kind: "center" })之类的调用,TypeScript无法从匿名参数中推断出类型。

您可以在调用通用Shape方法时将type variable指定为of来解决您的问题:

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

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