TypeScript 精通指南
·
TypeScript 精通指南
TypeScript 是 JavaScript 的超集,提供了强大的类型系统和现代编程特性。要精通 TypeScript,需要深入理解以下几个核心领域:
1. 类型系统深度掌握
基础类型
// 原始类型
let isDone: boolean = false;
let decimal: number = 6;
let color: string = "blue";
// 数组
let list: number[] = [1, 2, 3];
let genericList: Array<number> = [1, 2, 3];
// 元组
let tuple: [string, number] = ["hello", 10];
高级类型
// 联合类型
let id: string | number;
// 交叉类型
interface Named {
name: string;
}
interface Aged {
age: number;
}
type Person = Named & Aged;
// 类型别名
type StringOrNumber = string | number;
type Callback<T> = (data: T) => void;
// 条件类型
type IsString<T> = T extends string ? true : false;
type Result = IsString<"hello">; // true
// 映射类型
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Optional<T> = {
[P in keyof T]?: T[P];
};
2. 泛型深度应用
// 基础泛型
function identity<T>(arg: T): T {
return arg;
}
// 泛型约束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
// 泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
// 泛型默认值
interface ApiResponse<T = any> {
data: T;
status: number;
}
// 泛型条件类型
type Flatten<T> = T extends Array<infer U> ? U : T;
type StringArray = Flatten<string[]>; // string
3. 高级类型技巧
类型推断
// infer 关键字
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
type Parameters<T> = T extends (...args: infer P) => any ? P : never;
// 模板字面量类型
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type ApiEndpoint = `/api/${string}`;
type FullEndpoint = `${HttpMethod} ${ApiEndpoint}`;
// 递归类型
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};
类型守卫和断言
// 用户定义类型守卫
function isString(value: any): value is string {
return typeof value === 'string';
}
// 断言函数
function assert(condition: any, msg?: string): asserts condition {
if (!condition) {
throw new Error(msg);
}
}
function assertIsNumber(value: any): asserts value is number {
if (typeof value !== 'number') {
throw new Error('Not a number');
}
}
4. 装饰器(Decorators)
// 类装饰器
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
// 方法装饰器
function log(target: any, propertyName: string, descriptor: PropertyDescriptor) {
const method = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling ${propertyName} with`, args);
return method.apply(this, args);
};
}
// 属性装饰器
function format(formatString: string) {
return function (target: any, propertyKey: string) {
let value = target[propertyKey];
const getter = () => value;
const setter = (newVal: string) => {
value = formatString.replace('{0}', newVal);
};
Object.defineProperty(target, propertyKey, {
get: getter,
set: setter
});
};
}
@sealed
class User {
@format('Hello, {0}!')
greeting: string;
@log
sayHello(name: string) {
return `${this.greeting}, ${name}`;
}
}
5. 命名空间和模块
// 命名空间
namespace Geometry {
export interface Point {
x: number;
y: number;
}
export class Circle {
constructor(public center: Point, public radius: number) {}
area(): number {
return Math.PI * this.radius ** 2;
}
}
}
// ES 模块
import { Circle, Point } from './geometry';
// 动态导入
async function loadModule() {
const module = await import('./dynamic-module');
module.doSomething();
}
6. 配置和工程化
tsconfig.json 深度配置
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"moduleResolution": "Node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"removeComments": false,
"noEmitOnError": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"incremental": true,
"tsBuildInfoFile": "./dist/.tsbuildinfo"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}
7. 性能优化和最佳实践
类型性能优化
// 避免过度使用 any
// 不好的做法
function processData(data: any): any {
// ...
}
// 好的做法
function processData<T>(data: T): Processed<T> {
// ...
}
// 使用 const 断言
const colors = ['red', 'green', 'blue'] as const;
type Color = typeof colors[number]; // "red" | "green" | "blue"
// 使用 satisfies 运算符(TS 4.9+)
const config = {
width: 100,
height: 200,
color: 'red'
} satisfies Record<string, string | number>;
错误处理模式
// Result 模式
type Result<T, E = Error> =
| { success: true; data: T }
| { success: false; error: E };
function safeJsonParse(text: string): Result<any> {
try {
const data = JSON.parse(text);
return { success: true, data };
} catch (error) {
return { success: false, error: error as Error };
}
}
8. 测试和调试
// 测试工具类型
type Expect<T extends true> = T;
type Equal<X, Y> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? true : false;
// 测试用例
type Test = Expect<Equal<1, 1>>;
// 调试类型
type Debug<T> = { [K in keyof T]: T[K] };
type Prettify<T> = {
[K in keyof T]: T[K];
} & {};
9. 现代 TypeScript 特性
模板字面量类型
type World = "world";
type Greeting = `hello ${World}`; // "hello world"
type Color = "red" | "blue";
type Size = "small" | "large";
type ButtonStyle = `${Size}-${Color}-button`;
// "small-red-button" | "small-blue-button" | "large-red-button" | "large-blue-button"
satisfies 运算符
const theme = {
primary: '#ff0000',
secondary: '#00ff00',
borderRadius: '8px'
} satisfies Record<string, string>;
// theme.borderRadius 是 string 类型,但值被约束
10. 实战模式
函数式编程模式
// 柯里化
type Curried<T, R> = T extends []
? R
: T extends [infer First, ...infer Rest]
? (arg: First) => Curried<Rest, R>
: never;
function curry<T extends any[], R>(fn: (...args: T) => R): Curried<T, R> {
return function curried(...args: any[]): any {
return args.length >= fn.length
? fn(...args)
: (...moreArgs: any[]) => curried(...args, ...moreArgs);
} as any;
}
要真正精通 TypeScript,建议:
- 深入理解类型系统 - 掌握泛型、条件类型、映射类型等高级特性
- 实践项目 - 在真实项目中应用 TypeScript
- 阅读源码 - 学习优秀的 TypeScript 项目源码
- 关注更新 - TypeScript 每个版本都有新特性
- 工具链熟练 - 掌握 ESLint、Prettier、构建工具等
需要我详细解释某个特定方面吗?
更多推荐
所有评论(0)