我想判断是否有合并到另一个类型的内部类型,所以我try 了:

type A = {
  field: number
}

namespace A {
  type B = {
    field: string
  }
}

type C = {
   field: boolean
}

// What should I write here?
type HasInnerB<T> = /* ??? */ ? true : false

type AHasInnerB = HasInnerB<A>; // Expected to be true since type A.B exists
type CHasInnerB = HasInnerB<C>; // Expected to be false since type C.B doesn't exist

我不确定这是否可行.

推荐答案

这目前是不可能的.在打字脚本中的声明会引入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只提供了generictype个参数和参数.表单HasInnerB<T>的任何效用都要求Ttype,而不是值.

因此,如果您编写HasInnerB<A>,则A与名为A的命名空间没有任何关系,该命名空间导出名为B的类型.因此,无论您如何实现HasInnerB<T>,它都不会像预期的那样工作.


为了开始实现这一点,TypeScrip必须添加允许您对值和名称空间进行抽象化的功能.目前,命名空间绝对没有这样的功能,而对于值,typeof operator只能直接作用于一个值,而不能作用于某个"值参数"(因此您可以编写typeof val,但无法编写type TypeOf<T> = typeof T,因为T是一个类型参数,而不是一个值参数).

如果实现的话,一些特性请求(如microsoft/TypeScript#17588microsoft/TypeScript#55521microsoft/TypeScript#56124)可能会使我们能够编写HasInnerB<T>,但这可能是一项艰巨的任务(这不是基本功能的困难,但处理它如何与语言的其余部分交互是棘手的部分),我不认为GitHub对这些功能有多大热情(截至2024-01-10,这些功能中最受欢迎的功能有54👍个,这是不可忽略的,但远远没有被认为是流行的),所以我非常怀疑这会很快发生,不幸的是.

Playground link to code

Typescript相关问答推荐

如何使用泛型类型访问对象

为什么从数组中删除一个值会删除打字错误?

返回同时具有固定键和变量键的对象的函数的返回类型

基于平台的重定向,Angular 为16

如何使用Zod使一个基于其他字段值的字段为必填字段?

Next.js错误:不变:页面未生成

TypeScrip 5.3和5.4-对`Readonly<;[...number[],字符串]>;`的测试版处理:有什么变化?

我可以以这样一种方式键入对象,只允许它的键作为它的值吗?

MatTool提示在角垫工作台中不起作用

如何在typescript中为this关键字设置上下文

TYPE FOR ARRAY,其中每个泛型元素是单独的键类型对,然后在该数组上循环

有没有可能创建一种类型,强制在TypeScrip中返回`tyPeof`语句?

创建一个TypeScrip对象并基于来自输入对象的约束定义其类型

在Reaction中折叠手风琴

为什么我的函数arg得到类型为Never?

在TypeScript中,如何通过一系列过滤器缩小类型?

垫子工具栏不起作用的Angular 布线

在打印脚本中将对象类型转换为数组

为什么受歧视的unions 在一种情况下运作良好,但在另一种非常类似的情况下却不起作用?

完全在类型系统中构建的东西意味着什么?