如何指定类型仅接受继承自另一类型的对象?
如何在TypeScript中声明仅接受继承自某类型的对象
嘿,我来帮你搞定这个TypeScript类型约束的问题!你想要的是让类型只接受B或者继承B的子类型(比如你的A),但你写的any extends B这种语法在TypeScript里是不合法的,咱们换正确的方式来实现:
1. 接口中的数组属性
首先看你接口里的children属性,其实你不需要写any & B或者错误的any extends B。因为TypeScript是结构类型系统,所有继承B的子类型(比如A)都可以赋值给B类型。所以最简单的写法就是直接用ReadonlyArray<B>:
export interface B { bProp: string; // 这个数组可以接受B本身,或者任何继承B的子类型(比如A) children: ReadonlyArray<B>; } export interface A extends B { aProp: string; } // 测试:完全合法 const testA: A = { aProp: "test", bProp: "testB", children: [ { bProp: "childB" }, // 纯B类型 { aProp: "childA", bProp: "childB" } // A类型 ] };
如果你希望children的类型和当前接口的类型保持一致(比如A的children只能是A类型数组),可以给B加上泛型约束:
export interface B<T extends B = B> { bProp: string; children: ReadonlyArray<T>; } export interface A extends B<A> { aProp: string; } // 此时A的children只能是A类型的数组 const testA: A = { aProp: "test", bProp: "testB", children: [ { aProp: "childA", bProp: "childB" } // 合法 // { bProp: "childB" } // 这里会报错,因为A的children要求是A类型 ] };
2. 函数参数的类型约束
你写的fun(obj: any extends B)报错,因为这种写法不符合TypeScript的语法规则。要约束函数参数必须是B或其子类型,有两种方式:
方式一:直接用B类型
如果不需要在函数里访问子类型特有的属性,直接把参数类型设为B即可,子类型可以正常传入:
class SomeClass { fun(obj: B) { console.log(obj.bProp); // 可以安全访问B的属性 } } const someInstance = new SomeClass(); someInstance.fun({ bProp: "test" }); // 纯B类型,合法 someInstance.fun({ aProp: "testA", bProp: "testB" }); // A类型,也合法
方式二:用泛型约束(推荐如果需要访问子类型属性)
如果你需要在函数里访问子类型特有的属性(比如A的aProp),可以用泛型加上extends约束:
class SomeClass { fun<T extends B>(obj: T) { console.log(obj.bProp); // 肯定存在的B属性 // 如果是A类型,我们可以用类型守卫来访问aProp if ('aProp' in obj) { console.log(obj.aProp); // 此时TypeScript知道obj是A类型 } } }
为什么你的写法不对?
any extends B不是合法的TypeScript类型语法。extends用于类型约束时,只能出现在泛型声明里(比如<T extends B>),用来限制泛型参数T必须是B的子类型,而不能直接写在类型位置(比如ReadonlyArray<any extends B>)。
内容的提问来源于stack exchange,提问作者renatoaraujoc
相关产品推荐
相关产品推荐

