如果我有一个函数将返回提供的值(如果不是容器)或容器内的值(如果提供的值是是容器),那么我该如何正确声明该函数的返回类型?例如:
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
}
此方法似乎无效,因为TypeScript编译器对return input
语句提出了错误:
Type 'T' is not assignable to type 'ContainedTypeOrItself<T>'.
由于我相信if
子句会过滤所有类型为Container
的对象,因此我认为当代码到达return input
语句时,T
不是{ {1}},因此Container
应该只键入本身,ContainedTypeOrItself<T>
。显然,鉴于编译器错误,我对这应该如何工作的理解是不正确的。
在我的另一个related question中,我了解了为什么不小心使用T
而使用三元运算符会导致与使用any
语句时产生不同的行为。但是,我仍然认为我太精打细算,无法理解代码的实际问题,并且已经多次阅读注释和答案。他们 did 确切地回答了那里的问题:为什么三元运算符和if-else
之间存在不同的行为,对此我深表感谢-正是我所要寻找的。但是,在这个问题上,我使用的是一个简单的示例(谢谢!),并尝试在键入时尽可能具体。即使尝试应用有关if-else
用法,三元运算符以及使用该答案中的简化代码的经验教训,我仍然无法解决为什么它不起作用的问题。
感谢您抽出宝贵的时间阅读本文并为您提供帮助!
答案 0 :(得分:1)
我认为这是过度工程的情况。如果我听不懂,请注意我,我将删除答案。
为什么我认为您的代码比它看起来要解决的复杂得多?
如果要平整包含的对象,则平整函数的返回类型应始终为 raw 类型,T
。
使用infer
关键字会使您的解决方案复杂化,因此,如果要实现的目标是获得平面对象T
,请不要尝试返回除T
之外的其他类型。>
您的类型ContainedTypeOrItself<T>
将被描述为像联合一样
type ContainedTypeOrItself<T> = Container<T> | T;
然后,flat函数看起来像
const getContainedValueOrSelf = <T>(input: ContainedTypeOrItself<T>): T =>
isContainer<T>(input)
? input.value
: input;
是的,三元运算得到了广泛支持,编译器完全理解。
几行显示平坦的行为
const container: Container<number> = { value: 6 };
const decontained: number = getContainedValueOrSelf(container);
const raw: number = getContainedValueOrSelf(6);
我想回答的问题看起来比您的代码简单得多,这使我感到怀疑。因此,如果我误解了您的问题,请警告我。