[英]Union type in generic function
I have code that looks like this: 我有看起来像这样的代码:
/** explains the absence of a value */
export interface None {
'is none because': string;
// has spaces to reduce likelihood of a non-None having this member
}
/** Either a value or a reason why that value is missing. */
export type Optional<a> = a | None;
/** Possible value actually is a value */
export function isSome<a>(optValue: Optional<a>): optValue is a {
return !('is none because' in optValue);
}
/** Possible value actually is absent */
export function isNone<a>(optValue: Optional<a>): optValue is None {
return 'is none because' in optValue;
}
/** Consider optional value, require users to consider both possibilities */
export function outOfOptional<a, r>(value: Optional<a>, haveSome: (some: a) => r, haveNone: (reason: string) => r): r {
if (isNone(value)) {
return haveNone(value['is none because']);
}
else {
return haveSome(value);
}
}
I'm finding two problems with this set-up, however. 但是,我发现此设置有两个问题。 Both are related to the automatic deduction of the generic types in these utility functions.
两者都与这些实用程序功能中泛型类型的自动推论有关。
First, isSome
does not seem to work as a typeguard: 首先,
isSome
似乎不能充当类型保护者:
if (isSome(value)) {
// value here is still treated as a | None
}
It seems that the default deduction here is isSome<Optional<a>>
, which quite frankly is wrong ( isSome<Optional<a>>
should expect an argument of Optional<Optional<a>>
, which is not what it's getting here). 似乎这里的默认推论是
isSome<Optional<a>>
,坦率地说,这是错误的( isSome<Optional<a>>
应该期望Optional<Optional<a>>
的参数,这不是它在这里得到的结果) 。 If I'm explicit and use isSome<a>
, then it works, but I decidedly do not want to do that. 如果我是明确的并且使用
isSome<a>
,那么它可以工作,但是我绝对不想这样做。
Alternatively, isNone
does work, which is why you see it used in outOfOptional
: value
has type a
in the else
block. 另外,
isNone
确实起作用,这就是为什么您看到它在outOfOptional
使用的outOfOptional
: value
在else
块中键入a
。
In addition, consider this usage of outOfOptional
: 另外,请考虑
outOfOptional
这种用法:
export function outOfBothOptional<a, b, r>(
one: Optional<a>, another: Optional<b>,
haveBoth: (one: a, another: b) => r,
haveFirst: (one: a) => r,
haveSecond: (another: b) => r,
haveNone: (none: string) => r
): r {
return outOfOptional(
one,
haveOne => outOfOptional(
another,
haveAnother => haveBoth(haveOne, haveAnother),
() => haveFirst(haveOne)
),
() => outOfOptional(
another,
haveSecond,
haveNone
)
);
}
Both haveOne
and haveAnother
are deduced to be a | None
haveOne
和haveAnother
都被推论为a | None
a | None
rather than a
, even though this leads to an error, and even though they could not be . a | None
而不是a
,即使这会导致错误,即使他们不能 。 In effect, outOfOptional
here seems to be treated as outOfOptional<Optional<a>>
, except that's wrong, for the same reason isSome<Optional<a>>
was wrong. 实际上,这里的
outOfOptional
似乎被视为outOfOptional<Optional<a>>
, outOfOptional<Optional<a>>
是错误的,原因是isSome<Optional<a>>
是错误的。 The first argument is Optional<a>
, not Optional<a> | None
第一个参数是
Optional<a>
,而不是Optional<a> | None
Optional<a> | None
or Optional<Optional<a>>
as that deduction would imply. Optional<a> | None
或Optional<Optional<a>>
因为这将暗示。 Given a first argument of Optional<a>
, the generic type of outOfOptional
must be a
and definitely not Optional<a>
. 给定
Optional<a>
的第一个参数, outOfOptional
的泛型类型必须为a
并且绝对不是Optional<a>
。
Why does TypeScript consider this a valid, and in fact more valid , deduction? 为什么TypeScript认为这是有效的,实际上更有效的推论? Is there anyway I can use
a | None
反正我可以使用
a | None
a | None
as an optional type, without having to explicitly indicate generic types in the related functions? a | None
一个作为可选类型,而不必在相关函数中明确指出泛型?
Your intuition that this should be inferrable is correct, and in fact the current nightly build of TypeScript ( npm install typescript@next
) does infer the correct type now. 您的直觉是正确的,事实上,当前每夜构建的TypeScript(
npm install typescript@next
)现在都可以推断出正确的类型。
See the PR that fixed this https://github.com/Microsoft/TypeScript/pull/5895 and the originating bug https://github.com/Microsoft/TypeScript/issues/5861 请参阅修复此https://github.com/Microsoft/TypeScript/pull/5895的PR和原始错误https://github.com/Microsoft/TypeScript/issues/5861
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.