TypeScript接口中定义兼容所有基类子类数组的正确语法是什么?
TypeScript 基类型子类型数组声明方案
普通混合存储场景直接用 SomeBase[] 即可
TypeScript 采用结构类型系统,所有继承/符合SomeBase结构的子类型实例,都可以直接赋值给SomeBase类型的变量,完全不需要枚举所有子类,后续新增继承SomeBase的接口也无需修改Foo的定义,写法如下:
interface SomeBase {} interface A extends SomeBase { aProp: string } interface B extends SomeBase { bProp: number } interface Foo { bar: SomeBase[] } // 示例使用:混合放入A、B实例完全合法 const test: Foo = { bar: [ { aProp: 'test' }, { bProp: 123 } ] }
需要保留子类型完整信息时用泛型约束
如果你需要bar数组只能存某一种特定子类型的实例、且要保留子类型独有的属性类型提示,可以给Foo加带约束的泛型,对应你提到的<? extends SomeBase>的语法等价于TS中的T extends SomeBase:
// 泛型T默认值设为SomeBase,不需要指定类型时可以直接用Foo interface Foo<T extends SomeBase = SomeBase> { bar: T[] } // 示例1:指定只能存A类型的数组 const fooA: Foo<A> = { bar: [{ aProp: 'a' }] } // 此时fooA.bar[0].aProp 会有完整的类型提示,不会丢失属性 // 示例2:默认情况和直接写SomeBase[]效果一致,支持混合存储 const fooMix: Foo = { bar: [ { aProp: 'a' }, { bProp: 123 } ] }
补充说明
如果需要从SomeBase[]类型的数组中取出元素调用子类型独有的属性/方法,只需要做类型收窄即可,比如使用if('aProp' in item)判断或者自定义类型谓词,即可获得对应子类型的类型提示。
内容的提问来源于stack exchange,提问作者ekjcfn3902039
相关产品推荐
相关产品推荐

