TypeScript 是一种由微软开发的 JavaScript 超集,它为 JavaScript 增加了静态类型检查、类、接口、泛型等特性,使得代码更加健壮、可维护、可扩展。但是在使用 TypeScript 进行开发过程中,我们也会遇到一些常见的坑。本文将介绍一些常见的坑,并提供解决方案和示例代码。
坑一:类型兼容性
TypeScript 的类型兼容性是基于结构子类型的,即只要两个类型的成员结构兼容,那么它们就是兼容的。例如:
// www.javascriptcn.com code example
interface Animal {
name: string;
age: number;
}
interface Cat {
name: string;
age: number;
meow(): void;
}
let animal: Animal = { name: 'Tom', age: 3 };
let cat: Cat = { name: 'Kitty', age: 2, meow: () => console.log('meow') };
animal = cat; // OK
cat = animal; // Error在上面的例子中,Animal 和 Cat 都有 name 和 age 属性,因此它们是兼容的。但是 Cat 还有一个 meow 方法,因此它不能赋值给 Animal,反过来也是不行的。
解决方案:
如果你想让 Cat 能够赋值给 Animal,可以使用类型断言:
animal = cat as Animal; // OK
或者使用类型兼容性更加严格的接口继承:
// www.javascriptcn.com code example
interface Animal {
name: string;
age: number;
}
interface Cat extends Animal {
meow(): void;
}
let animal: Animal = { name: 'Tom', age: 3 };
let cat: Cat = { name: 'Kitty', age: 2, meow: () => console.log('meow') };
animal = cat; // OK
cat = animal; // Error坑二:类型推断
TypeScript 的类型推断可以让我们省略类型注解,但是有时候它可能会出现一些奇怪的行为。例如:
let x = 3; x = 'hello'; // Error
在上面的例子中,我们没有给 x 指定类型,TypeScript 会根据它的初始值推断出它的类型为 number。但是当我们试图将一个字符串赋值给它时,就会出现类型错误。
解决方案:
给 x 显式指定类型:
let x: number = 3; x = 'hello'; // Error
坑三:类型守卫
TypeScript 的类型守卫可以让我们在运行时判断一个变量的类型,并在正确的分支中使用它。例如:
// www.javascriptcn.com code example
interface Bird {
fly(): void;
}
interface Fish {
swim(): void;
}
function getSmallPet(): Bird | Fish {
// ...
}
let pet = getSmallPet();
if (pet instanceof Bird) {
pet.fly();
} else if (pet instanceof Fish) {
pet.swim();
} else {
// Error: pet 没有 fly 或 swim 方法
}在上面的例子中,我们使用 instanceof 运算符判断 pet 的类型,并在正确的分支中使用它。但是当 pet 的类型是联合类型时,TypeScript 无法自动推断出正确的类型,需要手动进行类型断言:
// www.javascriptcn.com code example
let pet = getSmallPet();
if ((pet as Bird).fly) {
(pet as Bird).fly();
} else if ((pet as Fish).swim) {
(pet as Fish).swim();
} else {
// Error: pet 没有 fly 或 swim 方法
}这样做非常麻烦,并且容易出错。
解决方案:
使用自定义类型守卫:
// www.javascriptcn.com code example
function isBird(pet: Bird | Fish): pet is Bird {
return (pet as Bird).fly !== undefined;
}
function isFish(pet: Bird | Fish): pet is Fish {
return (pet as Fish).swim !== undefined;
}
let pet = getSmallPet();
if (isBird(pet)) {
pet.fly();
} else if (isFish(pet)) {
pet.swim();
} else {
// Error: pet 没有 fly 或 swim 方法
}这样做可以让代码更加清晰、健壮、可维护。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d1b221a941bf71343937a0