这目前是不可能的.在打字脚本中的声明会引入a named type, a named value, or a named namespace, or some combination of those.类型、值和命名空间的名称实际上彼此之间没有任何内在联系.你不能仅仅因为它们共享一个名字就从另一个访问它们.实际上,您可以有一个名为X
的类型、一个名为X
的值和一个名为X
的命名空间,它们都不以任何编程方式相关:
// a namespace named X which exports a type named N
namespace X {
export type N = { n: string };
}
const a: X.N = { n: "" }
// a value named X
const X = { v: "" };
X.v.toUpperCase();
// a type named X
type X = { t: string };
const b: X = { t: "" };
因此,这就像名称空间、值和类型生活在平行的世界中. 有些声明会引入多个同名的声明(所以class
声明会同时引入构造函数value和实例type; namespace
声明可以同时引入类型导出namespace和变量导出value),但是你仍然不能仅仅通过它们的名字就从另一个中访问一个.
请注意,这是not被认为是declaration merging.名为X
的类型和名为X
的值不会合并为一个对象.只有当多个声明都在同一个世界中引入同名实体时,才能发生描述合并(因此,两个values名为X
,或两个types名为X
,或两个namespaces名为X
)……实际上只允许某些合并(通常不能将两个值或两个类型别名等合并在一起).
从问题中还不清楚您希望在什么意义上判断名为B
的成员的任意实体,因为根据实体所在的世界,这有三种不同的含义.但目前,TypeScrip只提供了generic个type个参数和参数.表单HasInnerB<T>
的任何效用都要求T
是type,而不是值.
因此,如果您编写HasInnerB<A>
,则A
与名为A
的命名空间没有任何关系,该命名空间导出名为B
的类型.因此,无论您如何实现HasInnerB<T>
,它都不会像预期的那样工作.
为了开始实现这一点,TypeScrip必须添加允许您对值和名称空间进行抽象化的功能.目前,命名空间绝对没有这样的功能,而对于值,typeof
operator只能直接作用于一个值,而不能作用于某个"值参数"(因此您可以编写typeof val
,但无法编写type TypeOf<T> = typeof T
,因为T
是一个类型参数,而不是一个值参数).
如果实现的话,一些特性请求(如microsoft/TypeScript#17588或microsoft/TypeScript#55521或microsoft/TypeScript#56124)可能会使我们能够编写HasInnerB<T>
,但这可能是一项艰巨的任务(这不是基本功能的困难,但处理它如何与语言的其余部分交互是棘手的部分),我不认为GitHub对这些功能有多大热情(截至2024-01-10,这些功能中最受欢迎的功能有54👍个,这是不可忽略的,但远远没有被认为是流行的),所以我非常怀疑这会很快发生,不幸的是.
Playground link to code个