TS基本概念 TS,是 JavaScript 的超集
为什么要 TS • 从编程语言的动静来区分,TypeScript 属于静态类型的编程语言,JavaScript 属于动态类型的编程语言 • 静态类型:编译期做类型检查 • 动态类型:执行期做类型检查
• 代码编译和代码执行的顺序:1 编译 2 执行 • 对于 JS 来说:需要等到代码真正去执行的时候才能发现错误(晚) • 对于 TS 来说:在代码编译的时候(代码执行前)就可以发现错误(早)
并且,配合 VSCode 等开发工具,TS 可以提前到在编写代码的同时就发现代码中的错误,减少找 Bug、改 Bug 时间
TS基础 1. 类型注解 概念 :类型注解是TypeScript的核心特性,用于为变量、函数参数、返回值等添加类型信息,提供编译时类型检查。
语法规则 :
变量:变量名: 类型 = 值
函数参数:参数名: 类型
函数返回值:function 函数名(): 返回类型
对象:{ 属性名: 类型 }
作用 :
提供类型安全,在编译时发现错误
增强代码可读性和可维护性
提供更好的IDE支持和智能提示
基本类型注解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 let name : string = '张三' let age : number = 25 let isStudent : boolean = true let hobby : null = null let address : undefined = undefined function greet (name : string ): string { return `Hello, ${name} !` } const add = (a : number , b : number ): number => { return a + b } let numbers : number [] = [1 , 2 , 3 ] let names : Array <string > = ['张三' , '李四' ] let user : { name : string age : number isStudent : boolean } = { name : '张三' , age : 25 , isStudent : true }
可选参数和默认参数 概念 :可选参数使用?标记,表示参数可以传入也可以不传入;默认参数使用=提供默认值。
语法规则 :
可选参数:参数名?: 类型
默认参数:参数名: 类型 = 默认值
剩余参数:...参数名: 类型[]
使用场景 :
可选参数:当某些参数不是必需时使用
默认参数:为参数提供默认值,简化函数调用
剩余参数:处理不定数量的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function greet (name : string , age ?: number ): string { if (age) { return `Hello, ${name} , you are ${age} years old!` } return `Hello, ${name} !` } function createUser (name : string , age : number = 18 ): object { return { name, age } } function sum (...numbers : number [] ): number { return numbers.reduce ((total, num ) => total + num, 0 ) }
函数重载 概念 :函数重载允许同一个函数名有多个不同的函数签名,根据传入参数的类型或数量调用不同的实现。
语法规则 :
重载声明:function 函数名(参数): 返回类型
重载实现:function 函数名(参数: 联合类型): 返回类型
使用场景 :
同一个函数需要处理不同类型的参数
提供更精确的类型检查和更好的IDE提示
简化API设计,一个函数名处理多种情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function format (value : string ): string function format (value : number ): string function format (value : boolean ): string function format (value : string | number | boolean ): string { if (typeof value === 'string' ) { return value.toUpperCase () } else if (typeof value === 'number' ) { return value.toString () } else { return value ? 'true' : 'false' } } console .log (format ('hello' )) console .log (format (123 )) console .log (format (true ))
类型断言 概念 :类型断言告诉TypeScript编译器某个值的具体类型,类似于其他语言中的类型转换,但不进行运行时检查。
语法规则 :
值 as 类型 (推荐)
<类型>值 (不推荐,容易与JSX冲突)
使用场景 :
当你比TypeScript更了解某个值的类型时
处理any类型的值时
处理联合类型时进行类型收窄
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 let someValue : any = 'this is a string' let strLength : number = (someValue as string ).length let strLength2 : number = (<string >someValue).length function getLength (value : string | number ): number { if ((value as string ).length !== undefined ) { return (value as string ).length } else { return value.toString ().length } }
类型推断 概念 :类型推断是TypeScript自动分析代码并推断出变量、函数参数、返回值等类型的能力,无需显式声明类型。
语法规则 :
变量:let 变量名 = 值 (自动推断类型)
函数:function 函数名(参数) { return 值 } (自动推断返回类型)
对象:let 对象名 = { 属性: 值 } (自动推断对象结构)
使用场景 :
简化代码,减少冗余的类型声明
提高开发效率
保持代码简洁性
注意 :虽然类型推断很方便,但在复杂场景下建议显式声明类型以提高代码可读性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 let name = '张三' let age = 25 let isStudent = true let numbers = [1 , 2 , 3 ] let user = { name : '张三' , age : 25 } function add (a : number , b : number ) { return a + b }
2. 基本类型 (Basic Types) 概念 :TypeScript提供了多种基本数据类型,用于描述不同类型的数据。
语法规则 :
原始类型:string、number、boolean、null、undefined
数组类型:类型[] 或 Array<类型>
元组类型:[类型1, 类型2, ...]
对象类型:{ 属性名: 类型 }
原始类型 1 2 3 4 5 6 7 8 9 10 11 12 13 let name : string = '张三' let age : number = 25 let isStudent : boolean = true let hobby : null = null let address : undefined = undefined let numbers : number [] = [1 , 2 , 3 ]let names : Array <string > = ['张三' , '李四' ]let person : [string , number ] = ['张三' , 25 ]
对象类型 1 2 3 4 5 6 7 8 9 10 let user : { name : string age : number isStudent : boolean } = { name : '张三' , age : 25 , isStudent : true }
3. 联合类型和交叉类型 (Union and Intersection Types) 概念 :联合类型和交叉类型是TypeScript中组合类型的两种重要方式,用于处理复杂的类型关系。
语法规则 :
联合类型:类型1 | 类型2 | 类型3
交叉类型:类型1 & 类型2 & 类型3
作用 :
联合类型:表示值可以是几种类型中的任意一种
交叉类型:表示值必须同时满足多个类型的条件
使用场景 :
联合类型:处理多种可能的类型,API返回多种类型
交叉类型:组合多个接口,混入功能
联合类型 (Union Types) 概念 :联合类型表示一个值可以是几种类型中的任意一种,使用 | 分隔。
语法规则 :类型1 | 类型2 | 类型3
特点 :
值可以是其中任意一种类型
只能访问所有类型共有的属性或方法
需要进行类型收窄才能访问特定类型的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 type StringOrNumber = string | number function formatValue (value : StringOrNumber ): string { if (typeof value === 'string' ) { return value.toUpperCase () } else { return value.toString () } } type Status = 'pending' | 'success' | 'error' function handleStatus (status : Status ) { switch (status) { case 'pending' : console .log ('处理中...' ) break case 'success' : console .log ('成功!' ) break case 'error' : console .log ('错误!' ) break } } type Circle = { kind : 'circle' radius : number } type Rectangle = { kind : 'rectangle' width : number height : number } type Shape = Circle | Rectangle function getArea (shape : Shape ): number { switch (shape.kind ) { case 'circle' : return Math .PI * shape.radius * shape.radius case 'rectangle' : return shape.width * shape.height } }
交叉类型 (Intersection Types) 概念 :交叉类型表示一个值必须同时满足多个类型的条件,使用 & 分隔。
语法规则 :类型1 & 类型2 & 类型3
特点 :
值必须同时满足所有类型的条件
可以访问所有类型的属性和方法
常用于组合多个接口或类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 type Person = { name : string age : number } & { email : string phone : string } let person : Person = { name : '张三' , age : 25 , email : 'zhangsan@example.com' , phone : '13800138000' } interface Flyable { fly (): void } interface Swimmable { swim (): void } type Duck = Flyable & Swimmable let duck : Duck = { fly ( ) { console .log ('鸭子飞' ) }, swim ( ) { console .log ('鸭子游泳' ) } } type Logger = { log (message : string ): void } & { error (message : string ): void } let logger : Logger = { log (message : string ) { console .log (`LOG: ${message} ` ) }, error (message : string ) { console .error (`ERROR: ${message} ` ) } }
联合类型 vs 交叉类型 | 特性 | 联合类型 (|) | 交叉类型 (&) | |——|—————-|—————-| | 含义 | 值可以是其中任意一种类型 | 值必须同时满足所有类型 | | 访问属性 | 只能访问共有属性 | 可以访问所有属性 | | 类型收窄 | 需要类型收窄 | 不需要类型收窄 | | 使用场景 | 处理多种可能的情况 | 组合多个类型 |
类型守卫 (Type Guards) 概念 :类型守卫是运行时检查,用于在运行时确定值的类型。
语法规则 :function 函数名(参数): 参数 is 类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 function isString (value : any ): value is string { return typeof value === 'string' } function isNumber (value : any ): value is number { return typeof value === 'number' } function processValue (value : string | number ) { if (isString (value)) { console .log (value.toUpperCase ()) } else if (isNumber (value)) { console .log (value.toFixed (2 )) } } type Bird = { fly (): void } type Fish = { swim (): void } function move (animal : Bird | Fish ) { if ('fly' in animal) { animal.fly () } else { animal.swim () } }
4. 接口 (Interface) 概念 :接口是TypeScript中定义对象结构的一种方式,它描述了对象应该具有的属性和方法,但不提供具体实现。
语法规则 :
基本接口:interface 接口名 { 属性名: 类型 }
可选属性:属性名?: 类型
只读属性:readonly 属性名: 类型
函数接口:interface 接口名 { (参数): 返回类型 }
接口继承:interface 接口名 extends 父接口 { }
作用 :
定义对象的结构和契约
提供类型检查和智能提示
提高代码的可维护性和可读性
支持接口继承和实现
基本接口 1 2 3 4 5 6 7 8 9 10 11 12 interface User { name : string age : number email ?: string readonly id : number } let user : User = { name : '张三' , age : 25 , id : 1 }
函数接口 1 2 3 4 5 6 7 interface SearchFunc { (source : string , subString : string ): boolean } let mySearch : SearchFunc = function (source : string , subString : string ) { return source.indexOf (subString) > -1 }
接口继承 1 2 3 4 5 6 7 8 9 10 11 12 interface Shape { color : string } interface Square extends Shape { sideLength : number } let square : Square = { color : 'red' , sideLength : 10 }
5. 类型别名 (Type) 概念 :类型别名允许为任何类型创建一个新名称,提高代码的可读性和复用性。
语法规则 :
基本类型别名:type 别名名 = 类型
联合类型:type 别名名 = 类型1 | 类型2
交叉类型:type 别名名 = 类型1 & 类型2
对象类型:type 别名名 = { 属性名: 类型 }
使用场景 :
简化复杂的类型定义
创建联合类型和交叉类型
提高代码可读性
复用类型定义
6. 泛型 (Generics) 概念 :泛型允许在定义函数、接口或类时不预先指定具体的类型,而在使用时再指定类型,提高代码的复用性和灵活性。
语法规则 :
泛型函数:function 函数名<T>(参数: T): T
泛型接口:interface 接口名<T> { }
泛型类:class 类名<T> { }
泛型约束:<T extends 约束类型>
使用场景 :
创建可复用的组件
保持类型安全
提高代码灵活性
避免使用any类型
基本泛型使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function identity<T>(arg : T): T { return arg } let output = identity<string >('hello' ) let output2 = identity (123 ) interface GenericIdentityFn <T> { (arg : T): T } let myIdentity : GenericIdentityFn <number > = identityclass GenericNumber <T> { zeroValue : T add : (x : T, y : T ) => T constructor (zeroValue : T, addFn : (x: T, y: T) => T ) { this .zeroValue = zeroValue this .add = addFn } } let myGenericNumber = new GenericNumber <number >(0 , (x, y ) => x + y)let myGenericString = new GenericNumber <string >('' , (x, y ) => x + y)
多泛型参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function swap<T, U>(tuple : [T, U]): [U, T] { return [tuple[1 ], tuple[0 ]] } let swapped = swap<string , number >(['hello' , 42 ]) interface KeyValuePair <K, V> { key : K value : V } let pair : KeyValuePair <string , number > = { key : 'age' , value : 25 }
泛型默认值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 interface ApiResponse <T = any > { data : T status : number message : string } let response1 : ApiResponse = { data : 'hello' , status : 200 , message : 'OK' }let response2 : ApiResponse <User > = { data : { id : 1 , name : 'John' }, status : 200 , message : 'OK' }
泛型与数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function getFirstElement<T>(arr : T[]): T | undefined { return arr[0 ] } function getLastElement<T>(arr : T[]): T | undefined { return arr[arr.length - 1 ] } let numbers = [1 , 2 , 3 , 4 , 5 ]let first = getFirstElement (numbers) let last = getLastElement (numbers) function filterArray<T>(arr : T[], predicate : (item : T ) => boolean ): T[] { return arr.filter (predicate) } let evenNumbers = filterArray (numbers, n => n % 2 === 0 )
泛型与Promise 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function fetchData<T>(url : string ): Promise <T> { return fetch (url).then (response => response.json ()) } fetchData<User []>('/api/users' ).then (users => { console .log (users) }) async function getData<T>(url : string ): Promise <T> { const response = await fetch (url) return response.json () } const users = await getData<User []>('/api/users' )
泛型约束 (Generic Constraints) 概念 :泛型约束允许我们限制泛型参数必须满足某些条件,使用 extends 关键字。
语法规则 :<T extends 约束类型>
作用 :
限制泛型参数的类型范围
在泛型函数中访问约束类型的属性
提供更精确的类型检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 interface Lengthwise { length : number } function loggingIdentity<T extends Lengthwise >(arg : T): T { console .log (arg.length ) return arg } loggingIdentity ('hello' ) loggingIdentity ([1 , 2 , 3 ]) loggingIdentity (123 ) interface Printable { print (): void } interface Serializable { serialize (): string } function process<T extends Printable & Serializable >(item : T): void { item.print () item.serialize () } function getProperty<T, K extends keyof T>(obj : T, key : K): T[K] { return obj[key] } let person = { name : '张三' , age : 25 }let name = getProperty (person, 'name' ) let age = getProperty (person, 'age' ) let invalid = getProperty (person, 'email' ) type NonNullable <T> = T extends null | undefined ? never : Tfunction processValue<T>(value : NonNullable <T>): void { } function createArray<T extends string | number >(length : number , value : T): T[] { return Array (length).fill (value) } let stringArray = createArray (3 , 'hello' ) let numberArray = createArray (3 , 42 ) function getProperty<T, K extends keyof T>(obj : T, key : K): T[K] { return obj[key] } let person = { name : 'John' , age : 30 , city : 'New York' }let name = getProperty (person, 'name' ) let age = getProperty (person, 'age' ) function createInstance<T extends new (...args : any []) => any >( constructor : T, ...args : ConstructorParameters <T> ): InstanceType <T> { return new constructor (...args ) } class Person { constructor (public name : string , public age : number ) {} } let personInstance = createInstance (Person , 'John' , 30 )
泛型实用技巧 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 type Optional <T> = { [K in keyof T]?: T[K] } type Required <T> = { [K in keyof T]-?: T[K] } type ApiResponse <T> = T extends 'user' ? User : T extends 'post' ? Post : T extends 'comment' ? Comment : never type CustomPartial <T> = { [P in keyof T]?: T[P] } type CustomReadonly <T> = { readonly [P in keyof T]: T[P] } function createFactory<T>(type : new (...args : any []) => T) { return (...args : any []): T => new type (...args) } class Cache <T> { private cache = new Map <string , T>() get (key : string ): T | undefined { return this .cache .get (key) } set (key : string , value : T): void { this .cache .set (key, value) } has (key : string ): boolean { return this .cache .has (key) } } type EventMap = { 'user:created' : { id : number ; name : string } 'user:updated' : { id : number ; changes : Partial <User > } 'user:deleted' : { id : number } } class EventEmitter <T extends Record <string , any >> { private listeners = new Map <keyof T, Array <(data : T[keyof T] ) => void >>() on<K extends keyof T>(event : K, listener : (data : T[K] ) => void ): void { if (!this .listeners .has (event)) { this .listeners .set (event, []) } this .listeners .get (event)!.push (listener) } emit<K extends keyof T>(event : K, data : T[K]): void { const eventListeners = this .listeners .get (event) if (eventListeners) { eventListeners.forEach (listener => listener (data)) } } } const emitter = new EventEmitter <EventMap >()emitter.on ('user:created' , (data ) => { console .log (`User created: ${data.name} ` ) })
7. 类 (Class) 概念 :类是面向对象编程的基础,TypeScript中的类支持访问修饰符、继承、抽象类等特性。
语法规则 :
基本类:class 类名 { }
访问修饰符:public、private、protected
继承:class 子类 extends 父类 { }
抽象类:abstract class 类名 { }
抽象方法:abstract 方法名(): 返回类型
使用场景 :
面向对象编程
封装数据和行为
实现继承和多态
创建抽象类
基本类定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Person { name : string age : number constructor (name : string , age : number ) { this .name = name this .age = age } greet (): string { return `Hello, I'm ${this .name} ` } static createAdult (name : string ): Person { return new Person (name, 18 ) } } let person = new Person ('张三' , 25 )console .log (person.greet ()) let adult = Person .createAdult ('李四' )
访问修饰符 (Access Modifiers) 概念 :访问修饰符控制类成员的可访问性,包括 public、private、protected。
语法规则 :
public - 公共的,可以在任何地方访问
private - 私有的,只能在类内部访问
protected - 受保护的,只能在类内部和子类中访问
作用 :
封装数据,隐藏内部实现
控制接口的暴露程度
提高代码的安全性和可维护性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 class Animal { public name : string private age : number protected color : string constructor (name : string , age : number , color : string ) { this .name = name this .age = age this .color = color } public getName (): string { return this .name } private getAge (): number { return this .age } protected getColor (): string { return this .color } } class Dog extends Animal { constructor (name : string , age : number , color : string ) { super (name, age, color) } public getInfo (): string { console .log (this .name ) console .log (this .color ) return `${this .name} is ${this .color} ` } } let dog = new Dog ('旺财' , 3 , '棕色' )console .log (dog.name ) console .log (dog.getInfo ())
抽象类 (Abstract Classes) 概念 :抽象类是不能被实例化的类,用于定义子类必须实现的接口和共同行为。
语法规则 :
abstract class 类名 { } - 定义抽象类
abstract 方法名(): 返回类型 - 定义抽象方法
abstract 属性名: 类型 - 定义抽象属性
特点 :
不能被直接实例化
可以包含抽象方法和具体方法
子类必须实现所有抽象方法
用于定义通用接口和共同行为
使用场景 :
定义通用接口
强制子类实现特定方法
提供共同的基础功能
实现模板方法模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 abstract class Animal { abstract species : string abstract makeSound (): void move (): void { console .log ('Moving...' ) } sleep (): void { console .log ('Sleeping...' ) } } class Dog extends Animal { species : string = 'Canine' makeSound (): void { console .log ('Woof!' ) } wagTail (): void { console .log ('Wagging tail...' ) } } class Cat extends Animal { species : string = 'Feline' makeSound (): void { console .log ('Meow!' ) } purr (): void { console .log ('Purring...' ) } } let dog = new Dog ()dog.makeSound () dog.move () dog.sleep () dog.wagTail () let cat = new Cat ()cat.makeSound () cat.move () cat.sleep () cat.purr () function makeAnimalSound (animal : Animal ): void { animal.makeSound () } makeAnimalSound (dog) makeAnimalSound (cat)
8. 枚举 (Enum) 概念 :枚举是一组命名常量的集合,提供了一种定义命名常量的方式。
语法规则 :
数字枚举:enum 枚举名 { 成员1, 成员2 }
字符串枚举:enum 枚举名 { 成员1 = '值1', 成员2 = '值2' }
使用枚举:枚举名.成员名
使用场景 :
定义一组相关的常量
提高代码可读性
避免魔法数字
提供类型安全
数字枚举 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 enum Direction { Up = 1 , Down , Left , Right } let direction : Direction = Direction .Up console .log (direction) console .log (Direction [1 ]) console .log (Direction [2 ])
字符串枚举 1 2 3 4 5 6 7 8 9 10 11 12 13 enum Color { Red = 'red' , Green = 'green' , Blue = 'blue' } let color : Color = Color .Red console .log (color)
混合枚举 1 2 3 4 5 enum Mixed { No = 0 , Yes = 'yes' }
常量枚举 1 2 3 4 5 6 7 8 9 10 const enum Status { Pending , Success , Error } let status : Status = Status .Success
9. 高级类型 (Advanced Types) 概念 :高级类型是TypeScript提供的复杂类型系统,包括条件类型、映射类型等。
语法规则 :
条件类型:T extends U ? X : Y
映射类型:{ [K in keyof T]: NewType }
模板字面量类型:`template string`
使用场景 :
条件类型 (Conditional Types) 概念 :条件类型根据条件选择不同的类型,类似于三元运算符。
语法规则 :T extends U ? X : Y
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 type IsString <T> = T extends string ? true : false type Test1 = IsString <string > type Test2 = IsString <number > type NonNullable <T> = T extends null | undefined ? never : Ttype Test3 = NonNullable <string | null > type Test4 = NonNullable <number | undefined > type ReturnType <T> = T extends (...args : any []) => infer R ? R : never type Test5 = ReturnType <() => string > type Test6 = ReturnType <() => number >
映射类型 (Mapped Types) 概念 :映射类型基于旧类型创建新类型,通过遍历旧类型的属性来生成新类型。
语法规则 :{ [K in keyof T]: NewType }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 type CustomPartial <T> = { [K in keyof T]?: T[K] } type CustomReadonly <T> = { readonly [K in keyof T]: T[K] } interface User { name : string age : number email : string } type PartialUser = CustomPartial <User >type ReadonlyUser = CustomReadonly <User >type Getters <T> = { [K in keyof T as `get${Capitalize<string & K>} ` ]: () => T[K] } type UserGetters = Getters <User >
模板字面量类型 (Template Literal Types) 概念 :模板字面量类型使用模板字符串语法创建字符串字面量类型。
语法规则 :`template string`
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 type EventName <T extends string > = `on${Capitalize<T>} ` type ClickEvent = EventName <'click' > type ChangeEvent = EventName <'change' > type ApiEndpoint <T extends string > = `/api/${T} ` type UserEndpoint = ApiEndpoint <'users' > type ProductEndpoint = ApiEndpoint <'products' > type GetPropertyType <T, K extends string > = K extends keyof T ? T[K] : never type UserName = GetPropertyType <User , 'name' > type UserAge = GetPropertyType <User , 'age' >
10. 模块系统 (Module System) 概念 :模块系统允许将代码分割成多个文件,每个文件可以导出和导入功能。
语法规则 :
命名导出:export const/function 名称
默认导出:export default 值
命名导入:import { 名称 } from '模块'
默认导入:import 名称 from '模块'
全部导入:import * as 名称 from '模块'
使用场景 :
代码组织和分割
功能复用
避免全局污染
提高代码可维护性
1 2 3 4 5 6 7 8 9 10 11 12 13 export const name = 'TypeScript' export function greet (name : string ): string { return `Hello, ${name} !` } export default class User { name : string constructor (name : string ) { this .name = name } }
导入 1 2 3 4 5 6 7 8 import { name, greet } from './module' import User from './module' import * as utils from './utils'
11. 实用工具类型 (Utility Types) 概念 :实用工具类型是TypeScript内置的类型操作工具,用于创建新的类型。
语法规则 :
Partial<T> - 所有属性变为可选
Required<T> - 所有属性变为必需
Pick<T, K> - 选择特定属性
Omit<T, K> - 排除特定属性
Record<K, V> - 创建记录类型
使用场景 :
类型转换和操作
创建新的类型
简化复杂类型定义
提高类型复用性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 interface User { id : number name : string email : string age : number } type PartialUser = Partial <User >type RequiredUser = Required <User >type UserName = Pick <User , 'name' >type UserBasicInfo = Pick <User , 'id' | 'name' >type UserWithoutEmail = Omit <User , 'email' >type UserWithoutId = Omit <User , 'id' >type UserRecord = Record <string , User >type StatusRecord = Record <'pending' | 'success' | 'error' , string >function updateUser (id : number , updates : Partial <User > ): void { console .log (`Updating user ${id} with:` , updates) } function createUser (userData : Omit <User , 'id' > ): User { return { id : Math .random (), ...userData } } function getUserName (user : Pick <User , 'name' > ): string { return user.name }
12. 配置文件 (Configuration) 概念 :TypeScript配置文件用于控制编译器的行为和选项。
语法规则 :
配置文件:tsconfig.json
编译选项:"compilerOptions": { }
包含文件:"include": ["路径"]
排除文件:"exclude": ["路径"]
使用场景 :
控制编译行为
指定编译目标
配置模块系统
设置严格模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 { "compilerOptions" : { "target" : "ES2020" , "module" : "ESNext" , "lib" : [ "ES2020" , "DOM" ] , "outDir" : "./dist" , "rootDir" : "./src" , "strict" : true , "esModuleInterop" : true , "skipLibCheck" : true , "forceConsistentCasingInFileNames" : true , "declaration" : true , "sourceMap" : true } , "include" : [ "src/**/*" ] , "exclude" : [ "node_modules" , "dist" ] }
13. 最佳实践 (Best Practices) 概念 :TypeScript开发的最佳实践和推荐做法。
语法规则 :
严格模式:"strict": true
类型声明:let 变量名: 类型 = 值
接口优先:interface 接口名 { }
避免any:使用具体类型
使用场景 :
提高代码质量
减少运行时错误
提高开发效率
团队协作
推荐做法
启用严格模式 - 在tsconfig.json中设置"strict": true
使用接口定义对象结构 - 优先使用interface而不是type
合理使用泛型 - 提高代码复用性和类型安全
使用类型守卫 - 确保类型安全
避免使用any - 尽量使用具体类型
使用工具类型 - 利用TypeScript内置的工具类型
14. 装饰器 (Decorators) 概念 :装饰器是一种特殊类型的声明,可以附加到类、方法、属性或参数上,用于修改或增强它们的行为。
语法规则 :
类装饰器:@装饰器名 class 类名 { }
方法装饰器:@装饰器名 方法名() { }
属性装饰器:@装饰器名 属性名: 类型
参数装饰器:方法名(@装饰器名 参数: 类型) { }
使用场景 :
元编程和反射
框架开发(如Angular)
日志记录和性能监控
依赖注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 function sealed (constructor : Function ) { Object .seal (constructor) Object .seal (constructor.prototype ) } @sealed class Greeter { greeting : string constructor (message : string ) { this .greeting = message } greet ( ) { return "Hello, " + this .greeting } } function log (target : any , propertyName : string , descriptor : PropertyDescriptor ) { const method = descriptor.value descriptor.value = function (...args : any [] ) { console .log (`调用方法: ${propertyName} ` ) return method.apply (this , args) } } class Calculator { @log add (a : number , b : number ): number { return a + b } } function format (target : any , propertyKey : string ) { let value = target[propertyKey] const getter = function ( ) { return value } const setter = function (newVal : string ) { value = newVal.toUpperCase () } Object .defineProperty (target, propertyKey, { get : getter, set : setter, enumerable : true , configurable : true }) } class Person { @format name : string = 'john' } let person = new Person ()person.name = 'jane' console .log (person.name )
15. 命名空间 (Namespaces) 概念 :命名空间提供了一种组织代码的方式,避免全局命名冲突。
语法规则 :
定义命名空间:namespace 命名空间名 { }
导出成员:export 成员名
使用命名空间:命名空间名.成员名
使用场景 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 namespace MyMath { export function add (a : number , b : number ): number { return a + b } export function subtract (a : number , b : number ): number { return a - b } export namespace Advanced { export function multiply (a : number , b : number ): number { return a * b } } } let result1 = MyMath .add (5 , 3 ) let result2 = MyMath .Advanced .multiply (4 , 2 ) namespace MyMath { export function divide (a : number , b : number ): number { return a / b } } let result3 = MyMath .divide (10 , 2 )
16. 声明文件 (Declaration Files) 概念 :声明文件用于描述JavaScript库的类型信息,以.d.ts结尾。
语法规则 :
全局声明:declare global { }
模块声明:declare module '模块名' { }
类型声明:declare type 类型名 = 类型
使用场景 :
为JavaScript库添加类型支持
描述第三方库的API
提供类型定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 declare global { interface Window { myCustomProperty : string } } declare module 'lodash' { export function chunk<T>(array : T[], size : number ): T[][] export function debounce<T extends (...args : any []) => any >( func : T, wait : number ): T } declare type MyCustomType = { name : string value : number } window .myCustomProperty = 'hello' import { chunk, debounce } from 'lodash'
17. 错误处理 (Error Handling) 概念 :TypeScript提供了多种错误处理机制,包括类型错误、运行时错误等。
语法规则 :
类型错误:编译时检查
运行时错误:使用try-catch
自定义错误:继承Error类
使用场景 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 function processValue (value : string | number ): string { if (typeof value === 'string' ) { return value.toUpperCase () } else if (typeof value === 'number' ) { return value.toString () } else { throw new Error ('Invalid value type' ) } } function divide (a : number , b : number ): number { try { if (b === 0 ) { throw new Error ('Division by zero' ) } return a / b } catch (error) { console .error ('Error:' , error.message ) return 0 } } class ValidationError extends Error { constructor (message : string , public field : string ) { super (message) this .name = 'ValidationError' } } function validateUser (user : { name: string ; age: number } ): void { if (!user.name ) { throw new ValidationError ('Name is required' , 'name' ) } if (user.age < 0 ) { throw new ValidationError ('Age must be positive' , 'age' ) } } try { validateUser ({ name : '' , age : -1 }) } catch (error) { if (error instanceof ValidationError ) { console .error (`Validation error in ${error.field} : ${error.message} ` ) } }
概念 :TypeScript提供了多种性能优化技术,包括类型优化、编译优化等。
语法规则 :
类型优化:使用具体类型
编译优化:配置tsconfig.json
运行时优化:避免类型检查
使用场景 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 function processData (data : any ): any { return data } function processData<T>(data : T): T { return data } function getElement (id : string ): HTMLElement { return document .getElementById (id) as HTMLElement } const colors = ['red' , 'green' , 'blue' ] as const type Color = typeof colors[number ] const config = { apiUrl : 'https://api.example.com' , timeout : 5000 } satisfies { apiUrl : string timeout : number } const point = { x : 10 , y : 20 } as const type Point = typeof point
📝 总结 TypeScript 是一个强大的 JavaScript 超集,为 JavaScript 添加了静态类型系统。通过本指南,我们学习了:
🎯 核心概念
类型注解 - TypeScript 的基础,提供编译时类型检查
接口和类型别名 - 定义对象结构和类型
泛型 - 创建可复用的类型安全代码
类 - 面向对象编程支持
🚀 高级特性
联合类型和交叉类型 - 处理复杂类型关系
条件类型和映射类型 - 类型级别的编程
模板字面量类型 - 字符串类型操作
装饰器 - 元编程和框架开发
🛠️ 实用工具
模块系统 - 代码组织和分割
声明文件 - 为 JavaScript 库添加类型支持
配置文件 - 控制编译行为
错误处理 - 类型安全和运行时错误处理
💡 最佳实践
启用严格模式 - 获得最佳类型检查
使用接口定义对象结构 - 提高代码可读性
合理使用泛型 - 提高代码复用性
避免使用 any - 保持类型安全
使用工具类型 - 利用内置类型工具
编写声明文件 - 为第三方库提供类型支持