打字稿转译中断

typescript transpilation breaking

问题陈述:

定义类型为 number 的变量,但是当将任何字符串分配给此变量并尝试将其 transpile 转换为 JavaScript 时。 Transpiler 没有给出任何错误。

问题演示:

class.ts

class User {
    age:number;
    name:string;
    phone:number | string;

    constructor(a, n, p) {
        this.age = a;
        this.name = n;
        this.phone = p;
    }

    getDetails() {
        return "Age : " + this.age + ", Name : " + this.name + ", Phone : " + this.phone;
    }
}

var firstUser = new User("27", "Rohit", "945*****44");

console.log(firstUser.getDetails());

在上面的代码中,我们将 age 变量定义为 number,但是在创建 class User 的实例时,我将年龄设置为 "27" 这是字符串。因此,在转译时它应该抛出错误但它被转译为 JavaScript 没有任何错误。

转译输出:

但是在相同的代码库中,如果我在构造函数中直接将字符串分配给 this.age 变量。转译器抛出错误。

class.ts

class User {
    age:number;
    name:string;
    phone:number | string;

    constructor(a, n, p) {
        this.age = "27";
        this.name = n;
        this.phone = p;
    }

    getDetails() {
        return "Age : " + this.age + ", Name : " + this.name + ", Phone : " + this.phone;
    }
}

var firstUser = new User("27", "Rohit", "945*****44");

console.log(firstUser.getDetails());

转译输出:

这是预期的行为。您的构造函数有 3 个没有类型注释的参数,因此它们的隐式类型将为 any。您可以将任何内容分配给 any(因此您可以将 string 分配给 any)并且您可以从 any 分配(因此您可以分配 number 字段来自 any 类型的 a 参数)。基本上在这种情况下 any 会删除您传入的任何类型。

因为 a 应该是一个数字,我们应该提供一个明确的注释,然后当我们传入 string 时会得到一个错误(这是预期的行为)

class User {
    age:number;
    name:string;
    phone:number | string;

    constructor(a: number, n: string, p: number | string) {
        this.age = a;
        this.name = n;
        this.phone = p;
    }

    getDetails() {
        return "Age : " + this.age + ", Name : " + this.name + ", Phone : " + this.phone;
    }
}

var firstUser = new User("27", "Rohit", "945*****44"); // error
var secondUser = new User(27, "Rohit", "945*****44"); // ok

您可以避免必须指定两次类型并通过将字段声明为构造函数参数来进行赋值。下面的代码等价于上面的class:

class User {

    constructor(
        public age:number, // Both a constructor argument and a field declaration, the compiler will perform the this.age = age assignemet for us
        public name:string,
        public phone:number | string) {
    }

    getDetails() {
        return "Age : " + this.age + ", Name : " + this.name + ", Phone : " + this.phone;
    }
}

如果你想避免any类型的隐式参数和变量,你可以使用noImplicitAny编译器选项,如果没有指定类型注释并且类型不能是推断。