Typescript 带有联合的条件映射类型使函数不可调用 type Container=T扩展任何[]?ArrayContainer:ObjectContainer 类型ArrayContainer={ 集合(arr:T,索引:编号):无效 } 类型ObjectContainer={ 集合(对象:T):无效 } const testContainer={}作为任意容器 //不编译 testContainer.set(33)

Typescript 带有联合的条件映射类型使函数不可调用 type Container=T扩展任何[]?ArrayContainer:ObjectContainer 类型ArrayContainer={ 集合(arr:T,索引:编号):无效 } 类型ObjectContainer={ 集合(对象:T):无效 } const testContainer={}作为任意容器 //不编译 testContainer.set(33),typescript,Typescript,条件类型决定返回一个ObjectContainer | ObjectContainer,使得无法对ObjectContainer调用任何函数 有没有办法强制返回ObjectContainer 使用可用的最新2.8版本。似乎需要额外的类型参数 type Container<T> = T extends any[] ? ArrayContainer<T> : ObjectContainer<T> type ArrayContainer<T> = {

条件类型决定返回一个
ObjectContainer | ObjectContainer
,使得无法对ObjectContainer调用任何函数

有没有办法强制返回
ObjectContainer


使用可用的最新2.8版本。

似乎需要额外的类型参数

type Container<T> = T extends any[] ? ArrayContainer<T> : ObjectContainer<T>

type ArrayContainer<T> = {
  set(arr: T, index: number): void
}

type ObjectContainer<T> = {
  set(obj: T): void
}

const testContainer = {} as any as Container<{ boxedNumber: number } | number>

// Does not compile
testContainer.set(33)
type Container=T扩展任何[]?ArrayContainer:ObjectContainer;
类型ArrayContainer={
集合(arr:T,索引:编号):无效
}
类型ObjectContainer={
集合(对象:T):无效
}
const testContainer={}作为容器;
testContainer.set(10);

问题在于,条件类型将迭代联合中的类型,并将条件应用于联合中的每个项目并联合结果,因此
Container
的结果将等同于
ObjectContainer | ObjectContainer
而不是
ObjectContainer

您可以创建一个交叉点类型的
容器
和容器,其行为与您期望的
容器

const testContainer={}与Container和Container一样
testContainer.set(33)
testContainer.set({boxedNumber:19})

正如@TitianCernicovaDragomir所指出的,您的问题是
T中带有裸类型参数
T
的条件类型扩展了XXX?YYY:ZZZ
最终分布在
T
中的一个联合体上。这是,但有一个用于它的:“框”将
T
XXX
放入一个元组,如
[T]扩展[XXX]?YYY:ZZZ
。这使得条件不依赖于裸类型参数,并且不再分解联合。(任何
T
在协变位置结束的地方都应该工作…
{a:T}扩展{a:XXX}
也可以工作)。这很可能会继续工作并得到支持,因为他是推荐它的人,并且是打字脚本中的那个人

所以在你的情况下,你会这样做

const testContainer = {} as any as Container<{ boxedNumber: number }> & Container<number>
testContainer.set(33)
testContainer.set({ boxedNumber: 19})
type Container=[T]扩展了[any[]?ArrayContainer:ObjectContainer
它将把
Container
解释为
ObjectContainer
,如您所愿

但请注意,现在将
容器
解释为
对象容器
,因为
字符串| number[]
本身不是数组。可以吗?是否应该是
ObjectContainer | ArrayContainer
?或者
ObjectContainer和ArrayContainer
?还是别的什么?不确定


希望有帮助;祝你好运。

如果OP想阻止条件分布在联合体上,事实上的标准方法是将条件“装箱”到一个元组中,如
type Container=[T]extends[any[]?ArrayContainer:ObjectContainer
@jcalz我不知道:)10x。你能补充一下答案吗,它是你的:)?@jcalz噢,哇,我从来没有想到过。不管怎样,它还是有效的!这在未来打破的可能性有多大?如果你发布答案,我很高兴批准。嗯,好的,当然,让我查找文档,然后发布答案。我通常使用类似于
T[number&keyof T]
的方法来解决这个问题。或者你可以做丑陋的
[T]扩展[any[]?(T扩展任何[]?T[数字]:从不):难道你没有忘记实际的解决方案
类型容器=[t]扩展了[any[]?ArrayContainer:ObjectContainer
?我认为只有纯数组才能进入ArrayContainer,任何联合都可以进入ObjectContainer
const testContainer = {} as any as Container<{ boxedNumber: number }> & Container<number>
testContainer.set(33)
testContainer.set({ boxedNumber: 19})
type Container<T> = [T] extends [any[]] ? ArrayContainer<T> : ObjectContainer<T>