禁止与任何

时间:2018-04-19 18:07:33

标签: typescript

考虑以下函数重载:

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);

1 个答案:

答案 0 :(得分:7)

TypeScript确实不想禁止any匹配某个类型,因为这是any的重点。您可能想重新考虑依赖于拒绝any的任何代码,因此请谨慎行事。

话虽如此,您可以使用新的conditional types功能为any构建一个检测器,然后可以使用该检测器禁止any变量。

这是探测器:

type IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N; 

不满足类型约束0 extends 10不能分配给1),因此0 extends (1 & T)也不可能满足,因为{{ 1}}应该比(1 & T)更窄。但是,当1T时,会将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}}匹配}的唯一类型是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,并且由于anynever不匹配,它将无法满足约束。

当我们使用上述签名时,您会看到以下行为:

any

这就是你想要的。

希望有所帮助;祝你好运!