禁止与任何人通话 [英] Disallow call with any
问题描述
考虑以下函数重载:
function f(key: undefined);
function f(key: string | undefined, value: object | undefined);
我想使用单个显式未定义 f(undefined)
进行符合条件的调用,但对于所有其他情况需要两个参数.上面的重载工作正常,直到我传递一个类型为 any
的变量 - 似乎 any
可以转换为 undefined
(是的,这似乎合乎逻辑因为它是任何).
I want to make eligible calls with single explicit undefined f(undefined)
, but require two arguments for all other cases. And overloads above work fine, until I pass a variable with type any
- seems like any
can be casted to undefined
(yes, it seems logical as it is any).
如何禁止使用单个 any
参数进行调用?
How can I disallow call with single any
argumnent?
完整 演示代码:
function f(key: undefined);
function f(key: string | undefined, value: object | undefined);
function f(key: string | undefined, value?: object | undefined) {
console.log(key, value);
}
// No errors - RIGHT
f(undefined);
f("", {});
f("", undefined);
f(undefined, undefined);
f(undefined, {});
// Errors - RIGHT
f("");
// No errors - WRONG
declare var x: any;
f(x);
推荐答案
TypeScript 真的不想禁止 any
匹配类型,因为这是 any
的全部意义代码>.您可能想要重新考虑任何依赖于拒绝 any
的代码,所以请谨慎行事.
TypeScript really doesn't want to disallow any
from matching a type, since that's the whole point of any
. You might want to rethink any code which relies on rejecting any
, so tread lightly.
话虽如此,您可以使用新的 条件类型 功能,为any
构建检测器,然后可用于禁止any
变量.
That being said, you can use the new conditional types feature to build a detector for any
which can then be used to disallow an any
variable.
这是检测器:
type IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N;
类型约束0 extends 1
不满足(0
不可赋值给1
),所以应该是不可能的>0 extends (1 & T)
也可以满足,因为 (1 & T)
应该比 1
更窄.然而,当T
为any
时,它会将0 extends (1 & any)
减少到0 extends any
,这是满意的.那是因为 any
故意不健全并且作为几乎所有其他类型的超类型和子类型.因此,IfAny
检查 T
是否为 any
.如果是,则返回 Y
.如果不是,则返回 T
.让我们看看它是否有效:
The type constraint 0 extends 1
is not satisfied (0
is not assignable to 1
), so it should be impossible for 0 extends (1 & T)
to be satisfied either, since (1 & T)
should be even narrower than 1
. However, when T
is any
, it reduces 0 extends (1 & any)
to 0 extends any
, which is satisfied. That's because any
is intentionally unsound and acts as both a supertype and subtype of almost every other type. Therefore, IfAny<T, Y, N>
checks if T
is any
. If so, it returns Y
. If not, it returns T
. Let's see it work:
type IsAny<T> = IfAny<T, true, false>
const yes: IsAny<any> = true;
const no: IsAny<string> = false;
<小时>
记得我说过 any
匹配几乎所有其他类型.唯一不匹配any
的类型是never
:
Recall that I said any
matches almost every other type. The only type that doesn't match any
is never
:
declare const any: any;
const never: never = any; // error, any is not assignable to never
我们也需要这个事实,以便拒绝任何
参数.让我们将 f()
的第一个签名从
We need that fact too, in order to reject any
parameters. Let's change the first signature of f()
from
function f(key: undefined): void;
到
function f<K extends IfAny<K, never, undefined>>(key: K): void;
我们使 key
成为一个通用类型 K
,它被限制为 IfAny
.如果 K
不是 any
,那么约束就是 undefined
,所以 K
只能是 undefined
根据需要.如果 K
is any
,则该约束变为 never
,并且由于 any
不匹配never
,就会不满足约束条件.
We've made the key
a generic type K
that is constrained to IfAny<K, never, undefined>
. If K
is not any
, then that constraint is just undefined
, so K
can only be undefined
as desired. If K
is any
, then that constraint becomes never
, and since any
does not match never
, it will fail to meet the constraint.
当我们使用上述签名时,您会看到以下行为:
When we use the above signature, you see the following behavior:
f(undefined); // still works
f(""); // still error, "" is not assignable to undefined
declare var x: any;
f(x); // now error, any is not assignable to never
这就是你想要的.
希望有所帮助;祝你好运!
Hope that helps; good luck!
这篇关于禁止与任何人通话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!