TypeScript 4.9在2022年11月发布,带来了一些新特性。
本文是一篇TypeScript入门指南,从零开始讲解TypeScript的核心概念,包括类型系统、接口、泛型、类,以及4.9版本的新特性。
一、TypeScript是什么
1. 基本概念
TypeScript是JavaScript的超集。
- 在JavaScript的基础上,增加了类型系统
- 最终编译成JavaScript运行
- 可以在开发阶段发现错误
- 支持最新的JavaScript特性
简单说:TypeScript = JavaScript + 类型系统。
2. 为什么用TypeScript
用TypeScript的好处:
- 类型安全:在编译阶段发现类型错误
- 更好的IDE支持:智能提示、自动补全、重构
- 代码更易维护:类型就是文档
- 适合大型项目:多人协作更顺畅
- 渐进式采用:可以和JavaScript混合使用
3. 安装和使用
安装TypeScript:
npm install -g typescript编译:
tsc hello.ts会生成hello.js文件。
也可以用ts-node直接运行:
npm install -g ts-node
ts-node hello.ts二、基础类型
1. 基本类型
TypeScript的基本类型:
// 字符串
let name: string = "张三";
// 数字
let age: number = 25;
// 布尔值
let isStudent: boolean = true;
// 数组
let list: number[] = [1, 2, 3];
let list2: Array<number> = [1, 2, 3];
// 元组
let tuple: [string, number] = ["张三", 25];
// 枚举
enum Color { Red, Green, Blue }
let c: Color = Color.Green;
// Any
let anything: any = "可以是任何类型";
// Void
function sayHello(): void {
console.log("Hello");
}
// Null和Undefined
let u: undefined = undefined;
let n: null = null;
// Never
function error(message: string): never {
throw new Error(message);
}
// Unknown
let value: unknown = "未知类型";2. 类型推断
TypeScript有类型推断,不一定要显式声明类型:
let name = "张三"; // 推断为string
let age = 25; // 推断为number
// 但建议在函数参数和返回值上显式声明类型
function add(a: number, b: number): number {
return a + b;
}3. 联合类型
一个变量可以是多种类型:
let id: number | string;
id = 123; // OK
id = "abc"; // OK
id = true; // 错误使用联合类型时,需要类型收窄:
function printId(id: number | string) {
if (typeof id === "string") {
console.log(id.toUpperCase());
} else {
console.log(id);
}
}三、接口
1. 定义接口
接口用来定义对象的形状:
interface Person {
name: string;
age: number;
isStudent?: boolean; // 可选属性
readonly id: number; // 只读属性
}
let person: Person = {
name: "张三",
age: 25,
id: 1
};2. 接口继承
接口可以继承:
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
let dog: Dog = {
name: "旺财",
breed: "金毛"
};3. 函数接口
接口也可以定义函数类型:
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc = function(source, subString) {
return source.search(subString) !== -1;
};四、类
1. 基本类
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
move(distance: number = 0) {
console.log(`${this.name} moved ${distance}m`);
}
}
let animal = new Animal("动物");
animal.move(10);2. 继承
class Dog extends Animal {
breed: string;
constructor(name: string, breed: string) {
super(name);
this.breed = breed;
}
bark() {
console.log("汪汪汪");
}
move(distance: number = 5) {
console.log("跑着...");
super.move(distance);
}
}
let dog = new Dog("旺财", "金毛");
dog.bark();
dog.move(20);3. 访问修饰符
class Person {
public name: string; // 公开,默认
private age: number; // 私有,只能在类内部访问
protected id: number; // 受保护,类和子类可以访问
constructor(name: string, age: number, id: number) {
this.name = name;
this.age = age;
this.id = id;
}
}4. 抽象类
abstract class Animal {
abstract makeSound(): void;
move() {
console.log("移动中...");
}
}
class Cat extends Animal {
makeSound() {
console.log("喵喵喵");
}
}五、泛型
1. 基本泛型
泛型让函数和类可以支持多种类型:
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>("hello");
let output2 = identity(123); // 类型推断2. 泛型接口
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;3. 泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };4. 泛型约束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // 现在可以访问length了
return arg;
}六、高级类型
1. 类型别名
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
if (typeof n === "string") {
return n;
} else {
return n();
}
}2. 交叉类型
interface A {
a: string;
}
interface B {
b: number;
}
type C = A & B;
let c: C = {
a: "hello",
b: 123
};3. 类型守卫
function isString(value: any): value is string {
return typeof value === "string";
}
function process(value: string | number) {
if (isString(value)) {
console.log(value.toUpperCase());
} else {
console.log(value.toFixed(2));
}
}4. 映射类型
interface Person {
name: string;
age: number;
}
// 所有属性变为只读
type ReadonlyPerson = Readonly<Person>;
// 所有属性变为可选
type PartialPerson = Partial<Person>;
// 自定义映射
type MyReadonly<T> = {
readonly [P in keyof T]: T[P];
};七、TypeScript 4.9新特性
1. satisfies操作符
这是4.9最重要的新特性。
satisfies可以验证类型,同时保留字面量类型:
// 之前:类型推断太宽泛
const palette = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255]
};
// palette.red 被推断为 number[] | string,没有精确类型
// 用satisfies:验证类型,保留字面量类型
const palette2 = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255]
} satisfies Record<string, string | number[]>;
// palette2.red 精确推断为 number[]
// palette2.green 精确推断为 string2. 自动访问器(Auto-Accessors)
class Person {
accessor name: string;
constructor(name: string) {
this.name = name;
}
}
// 编译后会生成getter和setter3. in操作符收窄
interface Dog {
bark(): void;
}
interface Cat {
meow(): void;
}
function speak(animal: Dog | Cat) {
if ("bark" in animal) {
animal.bark(); // 收窄为Dog
} else {
animal.meow(); // 收窄为Cat
}
}4.9优化了in操作符的类型收窄。
4. 其他改进
- 更严格的检查
- 更好的错误提示
- 性能优化
- 支持更多的JavaScript新特性
八、最佳实践
1. 开启严格模式
在tsconfig.json中开启严格模式:
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true
}
}2. 尽量不用any
- any会失去类型保护
- 用unknown代替any
- 用类型断言时要小心
3. 善用接口和类型别名
- 接口适合定义对象形状
- 类型别名更灵活
- 根据场景选择
4. 善用泛型
- 泛型让代码更通用
- 但不要过度使用
- 简单场景用具体类型
5. 善用工具类型
TypeScript内置了很多工具类型:
- Partial<T>:所有属性可选
- Required<T>:所有属性必选
- Readonly<T>:所有属性只读
- Pick<T, K>:选取部分属性
- Omit<T, K>:排除部分属性
- Record<K, T>:构造对象类型
九、学习建议
1. 从JavaScript过渡
- 如果你已经会JavaScript,学TypeScript很快
- 先在现有项目中逐步引入
- 从类型注解开始
- 慢慢学习高级特性
2. 多写多练
- 理论学习之后,要多实践
- 用TypeScript写小项目
- 遇到问题查文档
- 不断积累
3. 看官方文档
- TypeScript官方文档很详细
- Handbook是最好的入门教程
- 定期看更新日志
- 了解新特性
4. 用好工具
- VS Code对TypeScript支持很好
- 安装ESLint和Prettier
- 配置tsconfig.json
- 善用IDE的智能提示
十、写在最后
TypeScript 4.9,是一个值得学习的版本。
它的类型系统,能让你的代码更安全、更易维护。satisfies操作符、自动访问器等新特性,让TypeScript更强大。
2022年了,TypeScript已经成为前端开发的标配。不管是React、Vue还是Node.js,都在拥抱TypeScript。学习TypeScript,是前端工程师的必修课。
最后,用一句话总结:"TypeScript是JavaScript的超集,增加了类型系统。从零开始,先学基础类型,再学接口、类、泛型,最后学高级类型。多写多练,就能掌握。"
愿你学好TypeScript,写出更安全的代码。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录