我遇到的一些代码是这样的:

export function foo(arg: string): arg is MyType {
    return ...
}

我还没能在文档或谷歌中搜索到is,这是一个很常见的词,基本上出现在每一页上。

关键字在这个上下文中做什么?


我知道的唯一用法是你的例子:在用户定义的type Guard中指定“类型谓词”(arg是MyType)

请参见本参考资料中的用户定义类型防护

这是另一个参考


有关更多信息,请参阅用户定义类型保护函数的参考。

function isString(test: any): test is string{
    return typeof test === "string";
}

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length); // string function
    }
}
example("hello world");

使用上述格式的类型谓词test is string(而不是仅使用布尔值作为返回类型),在调用isString()后,如果函数返回true, TypeScript将在调用函数保护的任何块中将类型缩小为字符串。 编译器会认为foo是下面保护的块中的字符串(并且只在下面保护的块中)

{
    console.log("it is a string" + foo);
    console.log(foo.length); // string function
}

类型谓词只在编译时使用。结果的.js文件(运行时)将没有区别,因为它不考虑TYPE。

我将在下面四个例子中说明它们的区别。

例如1: 上面的示例代码将不会有编译错误或运行时错误。

例如2: 下面的示例代码将有一个编译错误(以及一个运行时错误),因为TypeScript已经将类型缩小为字符串,并检查toExponential不属于字符串方法。

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
        console.log(foo.toExponential(2));
    }
}

例如3: 下面的示例代码没有编译错误,但会有一个运行时错误,因为TypeScript只会将类型缩小为受保护的块中的字符串,而不是后面的字符串,因此是foo。toExponential不会产生编译错误(TypeScript不认为它是字符串类型)。但是,在运行时,string没有toExponential方法,所以它会有运行时错误。

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
    }
    console.log(foo.toExponential(2));
}

例如:4: 如果我们不使用test is string (type predicate), TypeScript将不会在被保护的块中缩小类型,下面的示例代码将不会有编译错误,但会有运行时错误。

function isString(test: any): boolean{
    return typeof test === "string";
}
function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
        console.log(foo.toExponential(2));
    }
}

结论是,在编译时使用test is string(类型谓词)来告诉开发人员代码将有可能出现运行时错误。对于javascript,开发人员在编译时不会知道错误。这是使用TypeScript的优势。