Typescript-推断强类型递归索引类型

时间:2019-09-27 11:57:09

标签: typescript typescript-typings

动物界面和我的农场中的动物图开始:

export interface Animal {
   type: string;
   edible: boolean;
}
export interface Farmland{
   [key: string]: Animal;
}

一切正常。这是我的农场-

const farm: Farmland = {

  bob: { type: 'sheep', edible: true },
  daisy: { type: 'cow', edible: true }

}

现在,我的票价可能包含一些较小的部分,我想要一种可以包含动物或这些部分的新类型:

export interface FarmlandOrAnimalMap {
  [key: string]: Animal | Farmland;
}

const bigField: FarmlandOrAnimalMap = {

  bob: { type: 'sheep', edible: true },
  daisy: { type: 'cow', edible: true },

  pasture: {
    jack: { type: 'dog', edible: false }
  },
  pond: {
    donald: { type: 'duck', edible: true }
  },
  farmhouse: {
    hernietta: { type: 'monkey', edible: false }
  }
};

这似乎也可行-我可以在标记中愉快地引用{{bigField.pond.donald.edible}}(例如使用angular)和所有其他预期的对象属性。这是我不能做的-

export class AnimalOven{

  constructor() {

    const donald = bigField.pond.donald;

  }
}

错误是Property 'donald' does not exist on type 'Animal | Farmland'. Property 'donald' does not exist on type 'Animal'。 (构建应用程序时,角度编译器也会抛出此错误。)

打字稿显然知道bigField.pond 可能 是农田(具有字符串索引) 动物,所以我不确定为什么它不能在这里推断正确的类型。简而言之:

使用 strong-type 和{[key:index]: strong-type 的类型联合时,Typescript是否可以正确推断类型}?

(显然,可能会有更好的方法来创建我的农场和动物,使用键,适当使用数组;但是这里的问题确实与地图类型的 Typescript推断有关)

谢谢。

1 个答案:

答案 0 :(得分:0)

通过声明它为FarmlandOrAnimalMap,您告诉编译器该变量的内容比此处的实际内容更为通用。

如果删除bigField的类型注释,则将在派生整个对象树的类型时起作用。

对于任何类型FarmlandOrAnimalMap的变量,除非引入其他检查,否则编译器将永远无法推断属性是Animal还是Farmland