使用类型推导避免你的代码变糟糕
许多从 JS 转到 TS 的开发者第一件事就是将所有的代码都补上类型注解,其实很多情况下是没有必要的。
像
let x: number = 12;就可以直接写成
let = 12;TS 会自动推导 x 的类型,可以看见,当前 x 的类型被推导为 number,是正确的。
即使是复杂的对象,TS 也能准确的完成其类型的推导。
const = {
: "Sojourner Truth",
: {
: "Swartekill, NY",
: "c.1797",
},
: {
: "Battle Creek, MI",
: "Nov. 26, 1883",
},
};可以看见 person 也能过正确完成推导。
有些时候,TS 所进行的推导甚至比你自己以为的类型更为精确:
const axis1: string = "x";const axis2 = "y";对于 axis1 来说,string 类型并没有 axis2 所得到的推导类型 "y" 更为精准。
类型推导对于代码重构也更为方便,设想如下场景:
interface Product {
id: number;
name: string;
price: number;
}
function logProduct(product: Product) {
const id: number = product.id;
const name: string = product.name;
const price: number = product.price;
console.log(id, name, price);
}你定义了一个 Product 类型,并且在使用该类型数据时,取 id 数据时,你显式声明了变量的类型。
但是后来因为某些原因(可能是需求变更),id 的类型变为了 string,你可能会直接将 Product 定义中 id 的类型直接更改为 string,此时,logProduct 函数就会报错。
// @errors: 2552
interface Product {
id: string;
name: string;
price: number;
}
function logProduct(product: Product) {
const id: number = product.id;
const name: string = product.name;
const price: number = product.price;
console.log(id, name, price);
}但如果你在写函数 logProduct 时,不显式指定 id 的类型,而是让 TS 去完成类型推导,那么此时就不需要再去修改 logProduct 的代码。
interface Product {
id: string;
name: string;
price: number;
}
function logProduct(product: Product) {
const { id, name, price } = product;
console.log(id, name, price);
}当然,显式类型注解并非一无是处,在 TS 无法获取足够上下文信息从而正确完成类型推导时,类型注解就显得尤为重要,例如在定义函数参数类型时就是如此。
函数签名包含类型注解,函数体局部变量无需类型注解,此为理想的 TS 代码。
对于具有默认值的函数参数可以不使用类型注解,因为 TS 能从默认值推导其类型:
function (: string, base = 10) { // ...
}在使用回调函数时,函数参数类型可以自动推导。
在某些情况下,即使类型能够正确推导,但加上类型注解,在错误出现时,TS 能够更加精准地定位。
- 当使用字面量定义对象时
const elmo: Product = {
name: "Tickle Me Elmo",
id: "048188 627152",
price: 28.99,
};interface Product {
id: string;
name: string;
price: number;
}
function logProduct(product: Product) {
const { id, name, price } = product;
console.log(id, name, price);
}
const furby = {
name: "Furby",
id: 630509430963,
price: 35,
};
logProduct(furby);const furby: Product = {
name: "Furby",
id: 630509430963,
price: 35,
};
logProduct(furby);- 函数返回类型
显式定义函数返回类型后,对于具有多个 return 语句的函数来说,TS 能够对返回的类型是否一致作出判断。
另外,将函数返回类型和输入类型明确写出,对于你来说就像是给函数绘制了一份草图。
interface Vector2D {
: number;
: number;
}
function add(: Vector2D, : Vector2D) { return { : . + ., : . + . };
}在使用命名类型作为返回类型时,返回值可能不会推导为你所想要的类型,因此此时主动确认返回类型更好。
最后,标注返回类型后,TS 所需要做的推导工作会变少,这对大型项目来说具有很大的影响。
linter 的规则: no-inferrable-types 能够保证你代码中的类型注解是必要的(没有多余的)。
上次更新于