Typescript 打字稿';编号';无法用于索引对象常量上的类型

Typescript 打字稿';编号';无法用于索引对象常量上的类型,typescript,types,Typescript,Types,我想输入一个对象常量。为了简单起见,我们假设它看起来像这样: const obj = { outer1: { inner1: ['a', 'b'], inner2: ['c', 'd'], }, outer2: { inner3: ['e', 'f'], }, } as const 这个对象是我的应用程序的核心,所以我希望输入它的几个元素,以便在应用程序范围内进行验证。我没有问题限制外键和内键,因此: type O

我想输入一个对象常量。为了简单起见,我们假设它看起来像这样:

const obj = {
    outer1: {
        inner1: ['a', 'b'],
        inner2: ['c', 'd'],
    },
    outer2: {
        inner3: ['e', 'f'],
    },
} as const
这个对象是我的应用程序的核心,所以我希望输入它的几个元素,以便在应用程序范围内进行验证。我没有问题限制外键和内键,因此:

type ObjType = typeof obj
type OuterKeys = keyof ObjType
type InnerKeys<KOuter extends OuterKeys> = keyof ObjType[KOuter]
它生成的类型为
readonly['a',b']
,而不是
a | b
。因此,我进一步改进了上述类型,通过

type AOrB = Inner<'outer1', 'inner1'>[number]
类型AOrB=内部[编号]
这很好用。但是,在将其混合到类型本身时:

type Inner<
    KOuter extends OuterKeys,
    KInner extends keyof ObjType[KOuter]
> = ObjType[KOuter][KInner][number]
类型内部<
考特扩展了奥特凯斯,
KInner扩展了对象类型[KOuter]的键
>=对象类型[KOuter][KInner][number]

我收到错误
类型“number”不能用于索引类型[对象类型的常量表示]
。为什么会发生这种情况?我能解决这个问题吗?

我不是100%确定,但我认为typescript无法推断由于延迟类型推断,您的类型会导致数组。据我所知,typescript只评估泛型的部分,因为性能原因,它必须对泛型进行评估。当你写作时

type AOrB = Inner<'outer1', 'inner1'>[number]
type Inner<
    KOuter extends OuterKeys,
    KInner extends keyof ObjType[KOuter]
> = ObjType[KOuter][KInner][number]
只有泛型它还不需要计算,因为您没有指定'outer1'或'inner1',它不会检查
obj.outer1.inner1
后面的类型,然后错误地警告您不能使用索引类型。但您可以欺骗编译器,使其相信结果是一个具有以下内容的数组:

类型内部<
考特扩展了奥特凯斯,
KInner延伸到ObjKeys
>=对象类型[KOuter][KInner]仅扩展任何[]?对象类型[KOuter][KInner][number]:从不;
对于条件类型,编译器确保
ObjType[KOuter][KInner]
必须是一个数组,即使不计算泛型,因为否则它将落在else部分,我们知道这永远不会发生。不过有点老套


编辑:

我不是100%确定,但我认为typescript无法推断您的类型由于延迟类型推断而导致数组。据我所知,typescript只评估泛型的部分,因为性能原因,它必须对泛型进行评估。当你写作时

type AOrB = Inner<'outer1', 'inner1'>[number]
type Inner<
    KOuter extends OuterKeys,
    KInner extends keyof ObjType[KOuter]
> = ObjType[KOuter][KInner][number]
只有泛型它还不需要计算,因为您没有指定'outer1'或'inner1',它不会检查
obj.outer1.inner1
后面的类型,然后错误地警告您不能使用索引类型。但您可以欺骗编译器,使其相信结果是一个具有以下内容的数组:

类型内部<
考特扩展了奥特凯斯,
KInner延伸到ObjKeys
>=对象类型[KOuter][KInner]仅扩展任何[]?对象类型[KOuter][KInner][number]:从不;
对于条件类型,编译器确保
ObjType[KOuter][KInner]
必须是一个数组,即使不计算泛型,因为否则它将落在else部分,我们知道这永远不会发生。不过有点老套


编辑:

您的条件类型的工作原理与类似,这是我在编译器无法跟踪约束的情况下经常使用的。此外,此问题似乎是由编译器错误引起的,请参阅或。很高兴知道这是一个错误-我不确定我是否只是试图“破解”该语言或是做错了什么。我用过你的解决方案,效果很好,使用
Extract
来清理一下。谢谢你们两位!您的条件类型的工作方式类似于,这是我在编译器无法跟踪约束的情况下经常使用的。此外,此问题似乎是由编译器错误引起的,请参阅或。很高兴知道这是一个错误-我不确定我是否只是试图“破解”该语言或是做错了什么。我用过你的解决方案,效果很好,使用
Extract
来清理一下。谢谢你们两位!