具有扩展相同父类的不同类的项的未知大小的数组

时间:2018-05-14 02:43:44

标签: typescript

基本上要声明一个包含任意数量项的数组,哪些类型是同一基类的子类。我不知道有多少个子类(有些可以由第三方插件提供)。如果我声明像Array<BaseClass>这样的数组,我希望对每个文字项对象声明进行精确的类型检查,但是typescript迫使我进行强制转换以便键入check。由于类多态性,我或我的用户都不希望进行投射。

示例:

class Base {
  name: string
}
class Sub1 extends Base {
  prop1: number
}
class Sub2 extends Base {
  prop2:string
}
// there will be other Base subclasses - I don't know how much - some provided by third party plugins

// public function called by end users - I want exact type checking of items object literals and I don't expect to manually cast each of them as in the example: 

function f(arr: Base[]){
}

// This doesn't work: for some reason typescript assumes every item is of type Sub1 even if I explicitly declared the second item as Sub2 : 
f([
  {name: '1', prop1: 1} as Sub1, 
  {name: '1', prop2: '2'} as Sub2, 
])

// This does does work and do exact typechecking as I want but I still need to cast (and I don't think I should)

f([
  {name: '1', prop1: 1},
  {name: '1', prop2: '2'},
] as [Sub1, Sub2])

在类似的情况下,打字稿可以完成一项完美的工作。这是在调用重载方法或函数时。我不需要演员和打字稿能够完全匹配签名而不必投射enything。我想知道他们是否想要实现阵列&#34;这个自动项目推断&#34;)因为性能(可能有巨大的(json)数组)......

用户调用f()的唯一优雅方法是通过强制转换每个数组项。我不希望我的图书馆用户强行这样做。不硬也不明显。

用户是否有办法调用f()而无需进行强制转换?在面向对象的语言中,由于类的多态性,由于Sub1和Sub2是Base的实例,我(和我的用户)不希望在这里过去。

注意:因为我不知道所有Base子类(有些可能由第三方提供),所以我无法使用类型union(arr: Array<Sub1|Sub2>)定义f参数

在像Java这样的其他语言中,你声明这样的数组:Array<? extends Base> - 也许打字稿有类似的东西我没有。

谢谢!

1 个答案:

答案 0 :(得分:2)

您获得的错误是设计用于捕获拼写错误的错误。它触发的最常见原因是错误拼写的财产。此检查仅适用于对象初始化。

如果您有一个现有数组,只要它具有name属性,该函数就会乐意接受它。

var arr = [
    { name: '1', prop1: 1 },
    { name: '1', prop2: '2' }
];

f(arr);

更多事情

如果您正在处理创建项目的案例,您可以告诉编译器期望更多的事情:

class Base {
    name: string;
    [key: string]: any;
}

这使编译器对...

透明

肯定会有一个名字......而且可能还有其他一些属性。

交叉点类型

如果您不想破坏Base课程,可以使用Base和单独的Indexed类型创建交集类型,以使用以下技巧。< / p>

class Base {
    name: string;
}

type Indexed = { [key: string]: any; }

// ...

function f(...arr: (Base & Indexed)[]) {
}

// ...

给它一个名字

您可能要做的最后一次整理是给交叉点类型一个名称。如果您打算在多个地方使用它,这有助于整理一些事情。

// ...

type SubOfBase = Base & Indexed;

function f(...arr: SubOfBase[]) {
}