测试表达式是否失败类型检查

时间:2018-03-08 16:23:35

标签: unit-testing typescript

我正在用TypeScript编写一个库,我想检查我的类型定义是否正确。通常,我想检查变量是否具有某种静态类型。我通常这样做:

let expectedToBeString : string = Api.callFunction("param1", 2, []);

但有时候,在我不知情的情况下,类型可能会扩展到any,因此上面的表达式仍会编译。所以我想通过编写一个故意失败类型检查的表达式来确保 any

有时我也想检查我的重载集是否适用于合法类型,但不适用于非法类型,但确保这一点的唯一方法是引发编译错误。

如何验证是否应该引发编译错误?

1 个答案:

答案 0 :(得分:1)

有趣的问题。当TypeScript v2.8中发布conditional types时,假设在本月某个时间(2018年3月)出现,或者现在在typescript@next出现,您将可以执行以下操作:

type ReplaceAny<T, R> = 0 extends (1 & T) ? R : T

ReplaceAny<T, R>类型将为T ,除非 Tany,在这种情况下,它将为R。正常类型T不应满足0 extends (1 & T),因为1 & T应至少与1一样窄,0不是1的子类型}。但TypeScript中的any类型违反了规则:它被认为是所有其他类型(或多或少)的超类型和子类型。这表示1 & any变为any0 extends any为真。因此,0 extends (1 & T)的行为类似于any探测器。

现在我们可以制作这样的便利功能:

const replaceAny = <R>() => <T>(x: T): ReplaceAny<T,R> => x as any;

如果您调用replaceAny<{}>(),它会生成一个函数,该函数将接受任何输入,如果该输入的类型为{},则返回any类型的值。

因此,让我们研究一些场景:

declare const Api: {
    callFunctionS(...args: any[]): string,
    callFunctionN(...args: any[]): number,
    callFunctionA(...args: any[]): any,
}

let expectedToBeString: string;

expectedToBeString =
    replaceAny<{}>()(Api.callFunctionS("param1", 2, []));
    // okay

expectedToBeString =
    replaceAny<{}>()(Api.callFunctionN("param1", 2, []));
    // error, number not assignable to string

expectedToBeString =
    replaceAny<{}>()(Api.callFunctionA("param1", 2, []));
    // error, {} not assignable to string

前两个表现符合您的预期,其中expectedToBeStringcallFunctionS()感到满意,但对callFunctionN()感到愤怒。新的行为是它对callFunctionA()感到愤怒,因为replaceAny<{}>()导致返回值为{}而不是any,而{}是不能转让给string

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