如何为返回给定输入或输入中包含的成员的TypeScript方法编写返回类型?

如何为返回给定输入或输入中包含的成员的TypeScript方法编写返回类型?,typescript,typescript-generics,Typescript,Typescript Generics,如果我有一个函数将返回提供的值(如果它不是容器)或容器内的值(如果提供的值是容器),我如何正确声明该函数的返回类型?例如: interface Container<TValue> { value: TValue; } declare function isContainer<TContained>( object: unknown ): object is Container<TContained>; type ContainedTypeOrIts

如果我有一个函数将返回提供的值(如果它不是容器)或容器内的值(如果提供的值是容器),我如何正确声明该函数的返回类型?例如:

interface Container<TValue> {
  value: TValue;
}

declare function isContainer<TContained>(
  object: unknown
): object is Container<TContained>;

type ContainedTypeOrItself<T> = T extends Container<infer U> ? U : T

function getContainedValueOrSelf<T>(
  input: T,
): ContainedTypeOrItself<T> {
  if (isContainer<ContainedTypeOrItself<T>>(input)) {
    return input.value
  }

  return input
}
因为我相信
if
子句过滤了
Container
类型的所有对象,所以我认为当代码到达
返回输入
语句时,
T
不是
容器
,因此
ContainedTypeOrItself
应该是自己键入的,
T
。显然,考虑到编译器的错误,我对如何工作的理解是不正确的

在我的另一篇文章中,我了解了为什么在不小心使用
any
的情况下使用三元运算符会导致与使用
if-else
语句时不同的行为。然而,我仍然认为我太过密集,无法理解代码的实际错误,并且我已经多次阅读了那里的注释和答案。他们确实准确地回答了那里提出的问题:为什么三元运算符和
if else
之间有不同的行为,对此我很感激——这正是我想要的。然而,在这个问题中,我使用了一个更简单的例子(谢谢!),并试图在键入时尽可能具体。我仍然很难理解为什么它不起作用,即使是在尝试应用关于
任何
用法、三元运算符以及使用该答案中的简化代码时


感谢您花时间阅读本文并提供帮助

我认为这是一个过度工程的例子。如果我没有正确理解,请注意我,我将删除我的答案

为什么我认为您的代码比它试图解决的看起来复杂得多?
如果您打算展平包含的对象,则展平函数的返回类型应始终为原始类型,
T

使用
expert
关键字会使您的解决方案复杂化,因此,如果要实现的目标是获得平面对象
T
,请不要尝试返回除
T
以外的任何其他类型

您的类型
包含类型或自身
将被描述为类似union的类型

type ContainedTypeOrItself<T> = Container<T> | T;
type ContainedTypeOrItself=Container | T;
然后,平坦函数将如下所示

const getContainedValueOrSelf = <T>(input: ContainedTypeOrItself<T>): T =>
  isContainer<T>(input)
  ? input.value
  : input;
const getContainedValueOrSelf=(输入:ContainedTypeOrItself):T=>
iContainer(输入)
? 输入值
:输入;
是的,三元运算得到了广泛的支持,编译器也完全理解

有几行显示了平坦的行为

const container: Container<number> = { value: 6 };

const decontained: number = getContainedValueOrSelf(container);
const raw: number = getContainedValueOrSelf(6);
const-container:container={value:6};
const decontained:number=getContainedValueOrSelf(容器);
const raw:number=getContainedValueOrSelf(6);

这让我怀疑,我试图回答的问题看起来比你的代码要简单得多。因此,如果我误解了您的问题,请警告我。

这非常有效,肯定能解决问题。感谢您抽出时间阅读并回复!你的解决方案显然比我的简单。我想我仍然对为什么我的代码不起作用感到好奇(尽管可能过于复杂)——至少在我看来,这在理论上是正确的,但在您的示例中,您可以强制强制强制强制转换
将输入作为containedTypeOritsef返回
并实现
isContainer
函数,如
return!!输入.value
(只要
T
没有
value
键)。
const container: Container<number> = { value: 6 };

const decontained: number = getContainedValueOrSelf(container);
const raw: number = getContainedValueOrSelf(6);