考虑以下函数重载:
function f(key: undefined);
function f(key: string | undefined, value: object | undefined);
我希望使用单个显式未定义f(undefined)
进行符合条件的调用,但是对于所有其他情况需要两个参数。并且上面的工作正常,直到我传递类型为any
的变量 - 似乎any
可以转换为undefined
(是的,它似乎是合乎逻辑的,因为它是任何)。
如何禁止使用单个any
argumnent进行通话?
完整demo code:
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);
答案 0 :(得分:7)
TypeScript确实不想禁止any
匹配某个类型,因为这是any
的重点。您可能想重新考虑依赖于拒绝any
的任何代码,因此请谨慎行事。
话虽如此,您可以使用新的conditional types功能为any
构建一个检测器,然后可以使用该检测器禁止any
变量。
这是探测器:
type IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N;
不满足类型约束0 extends 1
(0
不能分配给1
),因此0 extends (1 & T)
也不可能满足,因为{{ 1}}应该比(1 & T)
更窄。但是,当1
为T
时,会将any
缩减为0 extends (1 & any)
,这是令人满意的。这是因为0 extends any
是故意unsound,并且作为的超类型和子类型几乎所有其他类型。因此,any
会检查IfAny<T, Y, N>
是否为T
。如果是,则返回any
。如果没有,则返回Y
。让我们看看它是否有效:
T
回想一下,我说type IsAny<T> = IfAny<T, true, false>
const yes: IsAny<any> = true;
const no: IsAny<string> = false;
匹配几乎所有其他类型。 与<{1}}匹配1>}的唯一类型是any
:
any
我们也需要这个事实,以便拒绝never
个参数。让我们从
declare const any: any;
const never: never = any; // error, any is not assignable to never
的第一个签名
any
到
f()
我们已将function f(key: undefined): void;
设为限制为function f<K extends IfAny<K, never, undefined>>(key: K): void;
的泛型key
。如果K
不是IfAny<K, never, undefined>
,那么该约束只是K
,因此any
只能根据需要undefined
。如果K
undefined
,那么该约束将变为K
,并且由于any
与never
不匹配,它将无法满足约束。
当我们使用上述签名时,您会看到以下行为:
any
这就是你想要的。
希望有所帮助;祝你好运!