TypeScript 中的 ‘is’ keyword

1,240 阅读2分钟

is

官方手册: user-defined type guard functions 

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

在调用isString()之后,使用上述格式的类型谓词test is string(而不是只对返回类型使用boolean),如果函数返回trueTypeScript 将在由函数调用保护的任何块中将类型缩小为string.编译器将认为“foo”在下面的保护块中是“string”(并且仅在下面的保护块中)

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

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

我将在以下四个示例中说明差异。

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

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

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 只会在受保护的块中而不是之后将类型缩小为 string,因此foo.toExponential 不会创建编译错误(TypeScript不认为它是一个 string 类型)。但是,在运行时,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(类型谓词),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 的优势。

参考资料

stackoverflow.com/questions/4…