引言
TypeScript作为JavaScript的超集,为现代前端开发带来了强大的类型系统和面向对象编程能力。它不仅在编译时提供类型检查,还支持ECMAScript的最新特性,极大地提高了代码的可维护性和开发体验。本文将深入探讨TypeScript的核心特性,包括类型检查、接口泛型、装饰器等底层实现原理,并补充类型推断、高级类型、工程化实践等关键内容,通过完整代码示例展示TypeScript在真实项目中的应用价值。
一、类型检查的简单实现
运行时类型检查的基础
TypeScript在编译时进行类型检查,但理解其背后的原理有助于我们实现运行时类型检查。
// 1.1 基础类型检查器
class TypeChecker {
static isString(value) {
return typeof value === "string";
}
static isNumber(value) {
return typeof value === "number" && !isNaN(value);
}
static isBoolean(value) {
return typeof value === "boolean";
}
static isArray(value) {
return Array.isArray(value);
}
static isObject(value) {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
static isFunction(value) {
return typeof value === "function";
}
static isNull(value) {
return value === null;
}
static isUndefined(value) {
return typeof value === "undefined";
}
// 复合类型检查
static isType(value, expectedType) {
switch (expectedType) {
case "string":
return this.isString(value);
case "number":
return this.isNumber(value);
case "boolean":
return this.isBoolean(value);
case "array":
return this.isArray(value);
case "object":
return this.isObject(value);
case "function":
return this.isFunction(value);
case "null":
return this.isNull(value);
case "undefined":
return this.isUndefined(value);
default:
throw new Error(`Unsupported type: ${expectedType}`);
}
}
}
console.log(TypeChecker.isString("hello")); // true
console.log(TypeChecker.isNumber(42)); // true
console.log(TypeChecker.isType([1, 2, 3], "array")); // true
// 1.2 增强的类型检查器
class EnhancedTypeChecked {
static types = {
string: (value) => typeof value === "string",
number: (value) => typeof value === "number" && !isNaN(value),
boolean: (value) => typeof value === "boolean",
array: (value) => Array.isArray(value),
object: (value) =>
value !== null && typeof value === "object" && !Array.isArray(value),
function: (value) => typeof value === "function",
null: (value) => value === null,
undefined: (value) => typeof value === "undefined",
// 自定义类型
email: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
uuid: (value) =>
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(
value
),
date: (value) => value instanceof Date,
// 联合类型
union: (value, types) => types.some((type) => this.check(value, type)),
// 字面量类型
literal: (value, expected) => vaue === expected,
};
static check(value, type) {
if (typeof type === "string") {
const checker = this.types[type];
return checker ? checker(value) : false;
}
if (typeof type === "object" && type.type) {
if (type.type === "union") {
return this.types.union(value, type.types);
}
if (type.type === "literal") {
return this.types.literal(value, type.value);
}
}
return false;
}
static validate(value, schema) {
if (typeof schema === "string") {
return this.check(value, schema);
}
if (Array.isArray(schema)) {
// 数组类型
if (!this.check(value, "array")) {
return false;
}
const [itemType] = schema;
return value.every((item) => this.validate(item, itemType));
}
if (typeof schema === "object" && !Array.isArray(schema)) {
// 对象类型
if (!this.check(value, "object")) return false;
for (const [key, propSchema] of Object.entries(schema)) {
if (!this.validate(value[key], propSchema)) {
return false;
}
}
return true;
}
return false;
}
}
// 使用示例
const schema = {
name: "string",
age: "number",
email: "email",
tags: ["string"],
address: {
street: "string",
city: "string",
},
};
const data = {
name: "John",
age: 30,
email: "john@example.com",
tags: ["developer", "typescript"],
address: {
street: "123 Main St",
city: "New York",
},
};
console.log(EnhancedTypeChecked.validate(data, schema)); // true
// 1.3 编译时类型检查模拟
function createTypeSafeProxy(target, schema) {
return new Proxy(target, {
set(obj, prop, value) {
if (schema[prop]) {
const isValid = EnhancedTypeChecked.validate(value, schema[prop]);
if (!isValid) {
throw new TypeError(
`Invalid type for property ${prop}. Expected ${JSON.stringify(
schema[prop]
)}, got ${typeof value}`
);
}
}
obj[prop] = value;
return true;
},
get(obj, prop) {
return obj[prop];
},
});
}
const userSchema = {
name: "string",
age: "number",
active: "boolean",
};
const user = createTypeSafeProxy({}, userSchema);
try {
user.name = "Alice"; // 成功
user.age = "25"; // Invalid type for property age. Expected "number", got string
} catch (error) {
console.error(error.message);
}
TypeScript编译器模拟
class SimpleTypeScriptCompiler {
constructor() {
this.typeRegistry = new Map();
this.errors = [];
}
// 解析类型注释
parseTypeAnnotation(code) {
const typeRegex = /:\s*([^{}\[\]]+|\{[^}]+\}|\[[^\]]+\])/g;
const matches = [];
let match;
while ((match = typeRegex.exec(code)) !== null) {
matches.push(match[1].trim());
}
return matches;
}
// 提取接口定义
extractInterface(code) {
const interfaceRegex = /interface\s+(\w+)\s*\{([^}]+)\}/g;
const interfaces = new Map();
let match;
while ((match = interfaceRegex.exec(code)) !== null) {
const [, name, body] = match;
const properties = {};
body.split(";").forEach((line) => {
const propMatch = line.trim().match(/(\w+)\s*:\s*([^;]+)/);
if (propMatch) {
const [, propName, propType] = propMatch;
properties[propName] = propType.trim();
}
});
interfaces.set(name, properties);
}
return interfaces;
}
// 检查函数类型
checkFunctionTypes(code, interfaces) {
const functionRegex =
/function\s+(\w+)\(([^)]*)\)\s*(?::\s*([^{]+))?\s*\{/g;
const errors = [];
let match;
while ((match = functionRegex.exec(code)) !== null) {
const [, functionName, params, returnType] = match;
// 检查参数类型
if (params) {
params.split(",").forEach((param) => {
const paramMatch = param.match(/(\w+)\s*:\s*(\w+)/);
if (paramMatch) {
const [, paramName, paramType] = paramMatch;
// 这里可以添加实际类型检查逻辑
}
});
}
// 这里可以添加返回值类型检查逻辑
}
return errors;
}
// 编译TypeScript代码
compile(code) {
this.errors = [];
// 提取接口
const interfaces = this.extractInterface(code);
// 检查类型
const typeErrors = this.checkFunctionTypes(code, interfaces);
this.errors.push(...typeErrors);
// 移除类型注释, 生成JavaScript代码
let jsCode = code
.replace(/:\s*([^{}\[\]]+|\{[^}]+\}|\[[^\]]+\])/g, "") // 移除参数和变量类型
.replace(/interface\s+\w+\s*\{[^}]+\}/g, "") // 移除接口定义
.replace(/\s*\/\/.*$/gm, "") // 移除注释
.trim();
return {
jsCode,
errors: this.errors,
interfaces: Array.from(interfaces.entries()),
};
}
}
// 使用示例
const tsCode = `
interface User {
name: string;
age: number;
}
function greet(user: User): string {
return "Hello, " + user.name;
}
const john: User = { name: "John", age: 30 };
console.log(greet(john));
`;
const compiler = new SimpleTypeScriptCompiler();
const result = compiler.compile(tsCode);
console.log("生成的JavaScript代码:");
console.log(result.jsCode);
console.log("提取的接口:", result.interfaces);
console.log("类型错误:", result.errors);
二、接口和泛型的模拟
接口的实现与模拟
// 2.1 接口检查器
class InterfaceChecker {
static interfaces = new Map();
// 定义接口
static defineInterface(name, structure) {
this.interfaces.set(name, structure);
}
// 检查对象是否实现接口
static implements(obj, interfaceName) {
const interfaceDef = this.interfaces.get(interfaceName);
if (!interfaceDef) {
throw new Error(`接口 ${interfaceName} 未定义`);
}
// 检查所有必需属性
for (const [prop, type] of Object.entries(interfaceDef.required || {})) {
if (!(prop in obj)) {
return false;
}
if (type && !this.checkType(obj[prop], type)) {
return false;
}
}
// 检查可选属性类型(如果存在)
for (const [prop, type] of Object.entries(interfaceDef.optional || {})) {
if (prop in obj && type && !this.checkType(obj[prop], type)) {
return false;
}
}
// 检查方法
for (const method of interfaceDef.methods || []) {
if (!(method in obj) || typeof obj[method] !== 'function') {
return false;
}
}
return true;
}
// 类型检查
static checkType(value, type) {
if (typeof type === 'string') {
switch (type) {
case 'string': return typeof value === 'string';
case 'number': return typeof value === 'number' && !isNaN(value);
case 'boolean': return typeof value === 'boolean';
case 'object': return value !== null && typeof value === 'object';
default: return true;
}
}
if (Array.isArray(type)) {
return Array.isArray(value) && value.every(item => this.checkType(item, type[0]));
}
return true;
}
// 创建实现接口的类
static createClass(interfaceName, implementation) {
const interfaceDef = this.interfaces.get(interfaceName);
if (!interfaceDef) {
throw new Error(`接口 ${interfaceName} 未定义`);
}
// 创建类
const DynamicClass = class {
constructor(...args) {
if (implementation.constructor) {
implementation.constructor.apply(this, args);
}
// 验证实例是否符合接口
if (!this.implements(interfaceName)) {
throw new Error(`类未正确实现接口 ${interfaceName}`);
}
}
implements(interfaceName) {
return InterfaceChecker.implements(this, interfaceName);
}
};
// 添加接口要求的方法和属性
for (const [prop, descriptor] of Object.entries(implementation)) {
if (prop !== 'constructor') {
Object.defineProperty(DynamicClass.prototype, prop, descriptor);
}
}
return DynamicClass;
}
}
// 定义接口
InterfaceChecker.defineInterface('Serializable', {
required: {
toJSON: 'function',
fromJSON: 'function'
}
});
InterfaceChecker.defineInterface('User', {
required: {
id: 'number',
name: 'string'
},
optional: {
email: 'string',
age: 'number'
},
methods: ['save', 'delete']
});
// 2.2 使用接口
const UserClass = InterfaceChecker.createClass('User', {
constructor: function(id, name) {
this.id = id;
this.name = name;
},
save: {
value: function() {
console.log(`保存用户 ${this.name}`);
return true;
}
},
delete: {
value: function() {
console.log(`删除用户 ${this.name}`);
return true;
}
},
toJSON: {
value: function() {
return {
id: this.id,
name: this.name
};
}
}
});
const user = new UserClass(1, 'Alice');
console.log(user.implements('User')); // true
console.log(user.implements('Serializable')); // false
// 2.3 运行时接口验证装饰器
function implementsInterface(interfaceName) {
return function(target) {
const originalConstructor = target;
// 返回新的构造函数
const newConstructor = function(...args) {
const instance = new originalConstructor(...args);
if (!InterfaceChecker.implements(instance, interfaceName)) {
throw new Error(`类 ${target.name} 未实现接口 ${interfaceName}`);
}
return instance;
};
// 复制原型链
newConstructor.prototype = originalConstructor.prototype;
return newConstructor;
};
}
// 使用装饰器
@interface('User')
class AdminUser {
constructor(id, name) {
this.id = id;
this.name = name;
}
save() {
console.log('保存管理员');
}
delete() {
console.log('删除管理员');
}
}
try {
const admin = new AdminUser(1, 'Admin');
console.log('AdminUser创建成功');
} catch (error) {
console.error(error.message);
}
泛型的实现与模拟
// 2.4 泛型容器类
class GenericContainer {
constructor(value) {
this._value = value;
}
get value() {
return this._value;
}
set value(newValue) {
this._value = newValue;
}
// 泛型方法:转换值类型
map(transformer) {
return new GenericContainer(transformer(this._value));
}
// 检查类型(运行时)
checkType(expectedType) {
return typeof this._value === expectedType;
}
}
// 使用示例
const numberContainer = new GenericContainer(42);
console.log(numberContainer.value); // 42
console.log(numberContainer.checkType('number')); // true
const stringContainer = numberContainer.map(n => `数字: ${n}`);
console.log(stringContainer.value); // "数字: 42"
console.log(stringContainer.checkType('string')); // true
// 2.5 泛型函数工厂
function createGenericFunction(typeCheck) {
return {
// 泛型身份函数
identity: function(value) {
if (typeCheck && !typeCheck(value)) {
throw new TypeError('类型不匹配');
}
return value;
},
// 泛型数组操作
filterArray: function(arr, predicate) {
if (!Array.isArray(arr)) {
throw new TypeError('第一个参数必须是数组');
}
return arr.filter(predicate);
},
// 泛型映射
mapArray: function(arr, mapper) {
if (!Array.isArray(arr)) {
throw new TypeError('第一个参数必须是数组');
}
return arr.map(mapper);
}
};
}
// 创建特定类型的泛型函数
const numberFunctions = createGenericFunction(val => typeof val === 'number');
const stringFunctions = createGenericFunction(val => typeof val === 'string');
console.log(numberFunctions.identity(123)); // 123
console.log(stringFunctions.identity('hello')); // "hello"
// 2.6 泛型约束模拟
class GenericValidator {
static validate(value, constraints) {
// 类型约束
if (constraints.type && typeof value !== constraints.type) {
return false;
}
// 最小/最大值约束
if (constraints.min !== undefined && value < constraints.min) {
return false;
}
if (constraints.max !== undefined && value > constraints.max) {
return false;
}
// 长度约束
if (constraints.minLength !== undefined && value.length < constraints.minLength) {
return false;
}
if (constraints.maxLength !== undefined && value.length > constraints.maxLength) {
return false;
}
// 自定义验证函数
if (constraints.validator && !constraints.validator(value)) {
return false;
}
return true;
}
// 创建受约束的泛型类
static createConstrainedClass(constraints) {
return class ConstrainedContainer {
constructor(value) {
if (!GenericValidator.validate(value, constraints)) {
throw new Error('值不符合约束条件');
}
this._value = value;
}
get value() {
return this._value;
}
set value(newValue) {
if (!GenericValidator.validate(newValue, constraints)) {
throw new Error('新值不符合约束条件');
}
this._value = newValue;
}
};
}
}
// 使用泛型约束
const NumberContainer = GenericValidator.createConstrainedClass({
type: 'number',
min: 0,
max: 100
});
const StringContainer = GenericValidator.createConstrainedClass({
type: 'string',
minLength: 2,
maxLength: 50
});
try {
const numContainer = new NumberContainer(50); // 成功
console.log(numContainer.value); // 50
const strContainer = new StringContainer('Hello'); // 成功
console.log(strContainer.value); // "Hello"
// numContainer.value = 150; // 抛出错误
} catch (error) {
console.error(error.message);
}
// 2.7 泛型工具类型模拟
class GenericUtils {
// 模拟 Partial<T>
static partial(obj) {
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = obj[key];
}
}
return result;
}
// 模拟 Readonly<T>
static readonly(obj) {
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
Object.defineProperty(result, key, {
value: obj[key],
writable: false,
enumerable: true,
configurable: false
});
}
}
return Object.freeze(result);
}
// 模拟 Pick<T, K>
static pick(obj, keys) {
const result = {};
keys.forEach(key => {
if (key in obj) {
result[key] = obj[key];
}
});
return result;
}
// 模拟 Omit<T, K>
static omit(obj, keys) {
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key) && !keys.includes(key)) {
result[key] = obj[key];
}
}
return result;
}
// 模拟 Record<K, T>
static record(keys, valueCreator) {
const result = {};
keys.forEach(key => {
result[key] = valueCreator(key);
});
return result;
}
}
// 使用泛型工具
const user = {
id: 1,
name: 'John',
email: 'john@example.com',
age: 30
};
console.log(GenericUtils.pick(user, ['id', 'name'])); // { id: 1, name: 'John' }
console.log(GenericUtils.omit(user, ['email', 'age'])); // { id: 1, name: 'John' }
const readonlyUser = GenericUtils.readonly(user);
// readonlyUser.name = 'Bob'; // 在严格模式下会抛出错误
三、装饰器的实现原理
装饰器基础实现
// 3.1 基础装饰器工厂
function createDecorator(decoratorFunc) {
return function(...args) {
// 类装饰器
if (args.length === 1 && typeof args[0] === 'function') {
const targetClass = args[0];
return decoratorFunc(targetClass) || targetClass;
}
// 方法装饰器
if (args.length === 3 && typeof args[2] === 'object') {
const [target, property, descriptor] = args;
return decoratorFunc(target, property, descriptor) || descriptor;
}
// 属性装饰器
if (args.length === 2 && typeof args[1] === 'string') {
const [target, property] = args;
decoratorFunc(target, property);
return;
}
// 参数装饰器
if (args.length === 3 && typeof args[2] === 'number') {
const [target, property, parameterIndex] = args;
decoratorFunc(target, property, parameterIndex);
return;
}
return decoratorFunc(...args);
};
}
// 3.2 类装饰器
function classDecorator(logMessage) {
return createDecorator((targetClass) => {
// 保存原始构造函数
const originalConstructor = targetClass;
// 创建新的构造函数
const newConstructor = function(...args) {
console.log(`${logMessage}: 创建 ${originalConstructor.name} 实例`);
const instance = new originalConstructor(...args);
// 可以在这里修改实例
if (logMessage.includes('sealed')) {
Object.seal(instance);
}
return instance;
};
// 复制原型链
newConstructor.prototype = originalConstructor.prototype;
// 复制静态属性
Object.setPrototypeOf(newConstructor, originalConstructor);
return newConstructor;
});
}
// 3.3 方法装饰器
function methodDecorator(options = {}) {
return createDecorator((target, property, descriptor) => {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
// 前置处理
if (options.log) {
console.log(`调用方法: ${property}, 参数:`, args);
}
if (options.measureTime) {
console.time(`方法 ${property} 执行时间`);
}
// 执行原始方法
const result = originalMethod.apply(this, args);
// 后置处理
if (options.measureTime) {
console.timeEnd(`方法 ${property} 执行时间`);
}
if (options.log) {
console.log(`方法 ${property} 返回:`, result);
}
return result;
};
return descriptor;
});
}
// 3.4 属性装饰器
function propertyDecorator(defaultValue) {
return createDecorator((target, property) => {
// 创建私有属性名称
const privateProp = `_${property}`;
// 定义getter和setter
Object.defineProperty(target, property, {
get() {
return this[privateProp] !== undefined ? this[privateProp] : defaultValue;
},
set(value) {
this[privateProp] = value;
},
enumerable: true,
configurable: true
});
});
}
// 3.5 参数装饰器
function parameterDecorator(validator) {
return createDecorator((target, property, parameterIndex) => {
// 获取方法的参数验证元数据
if (!target.__parameterValidations) {
target.__parameterValidations = new Map();
}
const key = `${property}_${parameterIndex}`;
target.__parameterValidations.set(key, validator);
// 重写方法以添加参数验证
const originalMethod = target[property];
target[property] = function(...args) {
// 验证参数
const validator = target.__parameterValidations.get(`${property}_${parameterIndex}`);
if (validator && !validator(args[parameterIndex])) {
throw new Error(`参数 ${parameterIndex} 验证失败`);
}
return originalMethod.apply(this, args);
};
});
}
// 使用示例
@classDecorator('自动日志记录 - sealed')
class UserService {
@propertyDecorator('guest')
role;
constructor(name) {
this.name = name;
}
@methodDecorator({ log: true, measureTime: true })
greet(@parameterDecorator(val => typeof val === 'string') message) {
return `${this.name} 说: ${message}`;
}
@methodDecorator({ log: true })
setRole(@parameterDecorator(role => ['admin', 'user', 'guest'].includes(role)) newRole) {
this.role = newRole;
}
}
const service = new UserService('Alice');
console.log(service.role); // "guest" (默认值)
service.setRole('admin');
console.log(service.greet('你好!')); // 输出日志和结果
高级装饰器模式
// 3.6 依赖注入装饰器
class DependencyContainer {
static dependencies = new Map();
static register(token, implementation) {
this.dependencies.set(token, implementation);
}
static resolve(token) {
const dependency = this.dependencies.get(token);
if (!dependency) {
throw new Error(`未找到依赖: ${token}`);
}
if (typeof dependency === 'function') {
return new dependency();
}
return dependency;
}
}
function inject(token) {
return createDecorator((target, property, descriptor) => {
if (descriptor) {
// 方法参数注入
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
// 解析依赖
const dependency = DependencyContainer.resolve(token);
return originalMethod.call(this, dependency, ...args);
};
return descriptor;
} else {
// 属性注入
return {
get() {
return DependencyContainer.resolve(token);
},
enumerable: true,
configurable: true
};
}
});
}
// 3.7 路由装饰器(类似Angular/NestJS)
class Router {
static routes = new Map();
static get(path) {
return createDecorator((target, property, descriptor) => {
const originalMethod = descriptor.value;
const routeKey = `GET ${path}`;
this.routes.set(routeKey, {
controller: target.constructor.name,
method: property,
handler: originalMethod
});
descriptor.value = function(...args) {
console.log(`路由: ${routeKey}`);
return originalMethod.apply(this, args);
};
return descriptor;
});
}
static post(path) {
return createDecorator((target, property, descriptor) => {
const originalMethod = descriptor.value;
const routeKey = `POST ${path}`;
this.routes.set(routeKey, {
controller: target.constructor.name,
method: property,
handler: originalMethod
});
return descriptor;
});
}
static handleRequest(method, path) {
const routeKey = `${method} ${path}`;
const route = this.routes.get(routeKey);
if (route) {
console.log(`处理请求: ${routeKey}`);
// 实际中会创建控制器实例并调用方法
return route.handler;
}
return null;
}
}
// 3.8 验证装饰器
class Validator {
static validate(target, property, value) {
const validations = target.constructor.__validations;
if (validations && validations[property]) {
for (const validation of validations[property]) {
if (!validation.validator(value)) {
throw new Error(validation.message || `验证失败: ${property}`);
}
}
}
return true;
}
static required(message = '该字段是必填的') {
return createDecorator((target, property, descriptor) => {
if (descriptor) {
// 方法参数验证
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
const value = args[0];
if (!value && value !== 0 && value !== false) {
throw new Error(message);
}
return originalMethod.apply(this, args);
};
return descriptor;
} else {
// 属性验证
if (!target.constructor.__validations) {
target.constructor.__validations = {};
}
if (!target.constructor.__validations[property]) {
target.constructor.__validations[property] = [];
}
target.constructor.__validations[property].push({
validator: value => value != null && value !== '',
message
});
// 创建getter/setter
const privateProp = `_${property}`;
return {
get() {
return this[privateProp];
},
set(value) {
this[privateProp] = value;
},
enumerable: true,
configurable: true
};
}
});
}
static minLength(length, message) {
return createDecorator((target, property) => {
if (!target.constructor.__validations) {
target.constructor.__validations = {};
}
if (!target.constructor.__validations[property]) {
target.constructor.__validations[property] = [];
}
target.constructor.__validations[property].push({
validator: value => !value || value.length >= length,
message: message || `长度不能少于 ${length} 个字符`
});
});
}
static maxLength(length, message) {
return createDecorator((target, property) => {
if (!target.constructor.__validations) {
target.constructor.__validations = {};
}
if (!target.constructor.__validations[property]) {
target.constructor.__validations[property] = [];
}
target.constructor.__validations[property].push({
validator: value => !value || value.length <= length,
message: message || `长度不能超过 ${length} 个字符`
});
});
}
}
// 使用高级装饰器
@classDecorator('用户控制器')
class UserController {
@Router.get('/users')
getAllUsers() {
return ['Alice', 'Bob', 'Charlie'];
}
@Router.post('/users')
createUser(@Validator.required() name) {
return { id: 1, name };
}
}
// 用户模型
class User {
@Validator.required('用户名是必填的')
@Validator.minLength(3, '用户名至少3个字符')
@Validator.maxLength(20, '用户名最多20个字符')
username;
@Validator.required('密码是必填的')
@Validator.minLength(6, '密码至少6个字符')
password;
constructor(username, password) {
this.username = username;
this.password = password;
}
validate() {
for (const prop in this) {
if (this.hasOwnProperty(prop)) {
Validator.validate(this, prop, this[prop]);
}
}
}
}
// 测试
const user = new User('alice', 'password123');
user.validate(); // 成功
try {
const invalidUser = new User('a', '123');
invalidUser.validate(); // 抛出错误
} catch (error) {
console.error(error.message);
}
四、类型推断与类型系统
类型推断实现
// 4.1 类型推断引擎
class TypeInferenceEngine {
constructor() {
this.typeRegistry = new Map();
this.variableTypes = new Map();
}
// 推断变量类型
inferVariableType(name, value) {
let inferredType = this.inferValueType(value);
// 检查是否已经声明过类型
if (this.variableTypes.has(name)) {
const declaredType = this.variableTypes.get(name);
if (!this.isCompatible(inferredType, declaredType)) {
throw new Error(`类型不匹配: 变量 ${name} 声明为 ${declaredType}, 但推断为 ${inferredType}`);
}
return declaredType;
}
// 记录推断的类型
this.variableTypes.set(name, inferredType);
return inferredType;
}
// 推断值类型
inferValueType(value) {
if (value === null) return 'null';
if (value === undefined) return 'undefined';
const type = typeof value;
if (type === 'object') {
if (Array.isArray(value)) {
// 推断数组元素类型
if (value.length === 0) return 'any[]';
const elementType = this.inferValueType(value[0]);
return `${elementType}[]`;
}
if (value instanceof Date) return 'Date';
if (value instanceof RegExp) return 'RegExp';
// 推断对象结构
const structure = {};
for (const key in value) {
if (value.hasOwnProperty(key)) {
structure[key] = this.inferValueType(value[key]);
}
}
return JSON.stringify(structure);
}
return type;
}
// 检查类型兼容性
isCompatible(type1, type2) {
if (type1 === type2) return true;
// 处理any类型
if (type1 === 'any' || type2 === 'any') return true;
// 处理数组类型
if (type1.endsWith('[]') && type2.endsWith('[]')) {
const elementType1 = type1.slice(0, -2);
const elementType2 = type2.slice(0, -2);
return this.isCompatible(elementType1, elementType2);
}
// 处理对象类型
if (type1.startsWith('{') && type2.startsWith('{')) {
try {
const obj1 = JSON.parse(type1);
const obj2 = JSON.parse(type2);
for (const key in obj1) {
if (obj1.hasOwnProperty(key)) {
if (!obj2[key] || !this.isCompatible(obj1[key], obj2[key])) {
return false;
}
}
}
return true;
} catch {
return false;
}
}
return false;
}
// 推断函数返回类型
inferFunctionReturn(func, args) {
try {
const result = func.apply(null, args);
return this.inferValueType(result);
} catch {
return 'any';
}
}
}
// 使用示例
const engine = new TypeInferenceEngine();
const variables = {
name: 'Alice',
age: 30,
scores: [95, 88, 92],
profile: {
email: 'alice@example.com',
active: true
}
};
for (const [name, value] of Object.entries(variables)) {
const type = engine.inferVariableType(name, value);
console.log(`${name}: ${type}`);
}
// 4.2 联合类型推断
function inferUnionType(values) {
const types = new Set();
for (const value of values) {
const engine = new TypeInferenceEngine();
types.add(engine.inferValueType(value));
}
return Array.from(types).join(' | ');
}
console.log(inferUnionType([1, 'hello', true])); // "number | string | boolean"
// 4.3 上下文类型推断
class ContextualTyping {
static inferWithContext(value, context) {
const engine = new TypeInferenceEngine();
const valueType = engine.inferValueType(value);
// 如果有上下文类型,检查兼容性
if (context.expectedType) {
if (!engine.isCompatible(valueType, context.expectedType)) {
throw new Error(`上下文类型不匹配: 期望 ${context.expectedType}, 实际 ${valueType}`);
}
return context.expectedType;
}
return valueType;
}
}
const context = { expectedType: 'string' };
console.log(ContextualTyping.inferWithContext('hello', context)); // "string"
// ContextualTyping.inferWithContext(123, context); // 抛出错误
高级类型系统
// 4.4 条件类型模拟
class ConditionalType {
static extends(T, U) {
// 简化实现:检查T是否可以赋值给U
return T === U || T === 'any';
}
static extract(T, U) {
// 模拟 Extract<T, U>
if (this.extends(T, U)) {
return T;
}
return 'never';
}
static exclude(T, U) {
// 模拟 Exclude<T, U>
if (this.extends(T, U)) {
return 'never';
}
return T;
}
static nonNullable(T) {
// 模拟 NonNullable<T>
if (T === 'null' || T === 'undefined') {
return 'never';
}
return T;
}
static returnType(func) {
// 模拟 ReturnType<T>
try {
const result = func();
const engine = new TypeInferenceEngine();
return engine.inferValueType(result);
} catch {
return 'any';
}
}
static parameters(func) {
// 模拟 Parameters<T>
const funcStr = func.toString();
const paramMatch = funcStr.match(/\(([^)]*)\)/);
if (paramMatch) {
const params = paramMatch[1].split(',').map(p => p.trim());
return params.map(param => {
const [name, type] = param.split(':').map(s => s.trim());
return type || 'any';
});
}
return [];
}
}
// 使用示例
console.log(ConditionalType.extends('string', 'string')); // true
console.log(ConditionalType.extract('string | number', 'string')); // "string"
console.log(ConditionalType.exclude('string | number', 'string')); // "number"
console.log(ConditionalType.nonNullable('string | null')); // "string"
function sampleFunc(x, y) {
return x + y;
}
console.log(ConditionalType.returnType(() => sampleFunc(1, 2))); // "number"
console.log(ConditionalType.parameters(sampleFunc)); // ["any", "any"]
// 4.5 映射类型模拟
class MappedType {
static partial(T) {
// 模拟 Partial<T>
if (typeof T === 'string' && T.startsWith('{')) {
try {
const obj = JSON.parse(T);
const result = {};
for (const key in obj) {
result[key] = obj[key] + '?'; // 添加可选标记
}
return JSON.stringify(result);
} catch {
return T;
}
}
return T;
}
static required(T) {
// 模拟 Required<T>
if (typeof T === 'string' && T.startsWith('{')) {
try {
const obj = JSON.parse(T);
const result = {};
for (const key in obj) {
const type = obj[key].endsWith('?') ? obj[key].slice(0, -1) : obj[key];
result[key] = type;
}
return JSON.stringify(result);
} catch {
return T;
}
}
return T;
}
static readonly(T) {
// 模拟 Readonly<T>
if (typeof T === 'string' && T.startsWith('{')) {
try {
const obj = JSON.parse(T);
const result = {};
for (const key in obj) {
result[key] = 'readonly ' + obj[key];
}
return JSON.stringify(result);
} catch {
return T;
}
}
return T;
}
static record(K, T) {
// 模拟 Record<K, T>
const keys = K.split(' | ');
const result = {};
keys.forEach(key => {
const cleanKey = key.replace(/['"]/g, '');
result[cleanKey] = T;
});
return JSON.stringify(result);
}
}
// 使用示例
const userType = JSON.stringify({
name: 'string',
age: 'number?',
email: 'string'
});
console.log('Partial:', MappedType.partial(userType));
console.log('Required:', MappedType.required(userType));
console.log('Readonly:', MappedType.readonly(userType));
console.log('Record:', MappedType.record('"id" | "name"', 'string'));
五、模块与命名空间
TypeScript模块系统
// 5.1 模块加载器模拟
class TypeScriptModuleLoader {
constructor() {
this.modules = new Map();
this.exports = new Map();
this.moduleCache = new Map();
}
// 定义模块
define(moduleId, dependencies, factory) {
this.modules.set(moduleId, {
dependencies,
factory,
exports: {},
resolved: false
});
}
// 解析模块
async require(moduleId) {
if (this.moduleCache.has(moduleId)) {
return this.moduleCache.get(moduleId);
}
const module = this.modules.get(moduleId);
if (!module) {
// 尝试作为外部模块加载
return this.loadExternalModule(moduleId);
}
// 解析依赖
const depPromises = module.dependencies.map(dep => {
if (dep === 'exports') return {};
if (dep === 'require') return this.require.bind(this);
if (dep === 'module') return { id: moduleId, exports: {} };
return this.require(dep);
});
const dependencies = await Promise.all(depPromises);
// 执行工厂函数
const exports = module.factory.apply(null, dependencies);
// 缓存结果
module.exports = exports || {};
module.resolved = true;
this.moduleCache.set(moduleId, module.exports);
return module.exports;
}
// 加载外部模块(模拟)
async loadExternalModule(moduleId) {
console.log(`加载外部模块: ${moduleId}`);
// 模拟动态导入
if (moduleId.startsWith('.')) {
// 相对路径
const mockModule = await this.mockLoadModule(moduleId);
return mockModule;
}
// 假设是npm包
return {};
}
async mockLoadModule(path) {
// 模拟模块内容
const mockModules = {
'./math': {
add: (a, b) => a + b,
subtract: (a, b) => a - b
},
'./utils': {
format: str => str.toUpperCase(),
parse: str => JSON.parse(str)
}
};
await new Promise(resolve => setTimeout(resolve, 100)); // 模拟延迟
return mockModules[path] || {};
}
// 编译TypeScript模块
compileModule(source) {
// 移除类型注解
const jsCode = source
.replace(/:\s*\w+(?:<[^>]*>)?(?=\s*[;,=){}])/g, '') // 移除类型注解
.replace(/export\s+(?:default\s+)?/g, '') // 简化导出
.replace(/import\s+.*?from\s+['"](.+)['"]/g, '// 导入: $1'); // 注释化导入
return jsCode;
}
}
// 使用示例
const loader = new TypeScriptModuleLoader();
// 定义TypeScript模块
const mathSource = `
export function add(a: number, b: number): number {
return a + b;
}
export function subtract(a: number, b: number): number {
return a - b;
}
export default class Calculator {
multiply(a: number, b: number): number {
return a * b;
}
}
`;
const appSource = `
import { add } from './math';
import Calculator from './math';
export function calculate(): number {
const calc = new Calculator();
return add(10, calc.multiply(2, 3));
}
`;
// 编译模块
const mathJS = loader.compileModule(mathSource);
const appJS = loader.compileModule(appSource);
console.log('编译后的math模块:');
console.log(mathJS);
console.log('编译后的app模块:');
console.log(appJS);
// 5.2 命名空间实现
class NamespaceManager {
static namespaces = new Map();
static create(namespace, contents) {
if (!this.namespaces.has(namespace)) {
this.namespaces.set(namespace, {});
}
const ns = this.namespaces.get(namespace);
Object.assign(ns, contents);
// 暴露到全局
const parts = namespace.split('.');
let current = globalThis;
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
if (i === parts.length - 1) {
current[part] = ns;
} else {
current[part] = current[part] || {};
current = current[part];
}
}
return ns;
}
static get(namespace) {
return this.namespaces.get(namespace);
}
static export(namespace, exports) {
const ns = this.get(namespace) || this.create(namespace, {});
Object.assign(ns, exports);
}
}
// 使用命名空间
NamespaceManager.create('MyApp.Math', {
add: (a, b) => a + b,
subtract: (a, b) => a - b,
constants: {
PI: 3.14159,
E: 2.71828
}
});
NamespaceManager.create('MyApp.Utils', {
format: str => str.toUpperCase(),
validate: obj => obj != null
});
// 访问命名空间
console.log(MyApp.Math.add(2, 3)); // 5
console.log(MyApp.Utils.format('hello')); // "HELLO"
六、工程化与构建工具集成
TypeScript配置与编译
// 6.1 TypeScript配置解析器
class TSConfigParser {
static parse(config) {
const defaults = {
compilerOptions: {
target: 'es5',
module: 'commonjs',
strict: false,
esModuleInterop: true,
skipLibCheck: true,
forceConsistentCasingInFileNames: true
},
include: ['src/**/*'],
exclude: ['node_modules', 'dist']
};
return this.deepMerge(defaults, config);
}
static deepMerge(target, source) {
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (this.isObject(source[key]) && this.isObject(target[key])) {
this.deepMerge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
return target;
}
static isObject(item) {
return item && typeof item === 'object' && !Array.isArray(item);
}
static generateCompilerCommand(config) {
const options = config.compilerOptions;
const args = [];
for (const [key, value] of Object.entries(options)) {
const argName = `--${key}`;
if (typeof value === 'boolean') {
if (value) args.push(argName);
} else if (typeof value === 'string') {
args.push(`${argName} ${value}`);
} else if (Array.isArray(value)) {
args.push(`${argName} ${value.join(',')}`);
}
}
return `tsc ${args.join(' ')}`;
}
}
// 示例配置
const tsconfig = {
compilerOptions: {
target: 'es2020',
module: 'esnext',
lib: ['es2020', 'dom'],
outDir: './dist',
rootDir: './src',
strict: true,
moduleResolution: 'node',
baseUrl: '.',
paths: {
'@/*': ['src/*']
},
allowSyntheticDefaultImports: true
},
include: ['src/**/*.ts', 'src/**/*.tsx'],
exclude: ['node_modules']
};
const parsedConfig = TSConfigParser.parse(tsconfig);
console.log('解析后的配置:', parsedConfig);
console.log('编译器命令:', TSConfigParser.generateCompilerCommand(parsedConfig));
// 6.2 构建管道模拟
class TypeScriptBuildPipeline {
constructor(config) {
this.config = config;
this.steps = [];
}
addStep(name, processor) {
this.steps.push({ name, processor });
return this;
}
async build(sourceFiles) {
console.log('开始构建TypeScript项目...');
let processedFiles = sourceFiles;
for (const step of this.steps) {
console.log(`执行步骤: ${step.name}`);
if (Array.isArray(processedFiles)) {
const results = await Promise.all(
processedFiles.map(file => step.processor(file, this.config))
);
processedFiles = results;
} else {
processedFiles = await step.processor(processedFiles, this.config);
}
}
console.log('构建完成!');
return processedFiles;
}
}
// 构建步骤处理器
const processors = {
// 类型检查
typeCheck: async (file, config) => {
console.log(`类型检查: ${file.name}`);
// 模拟类型检查
if (file.name.includes('error')) {
throw new Error(`类型错误: ${file.name}`);
}
return file;
},
// 编译
compile: async (file, config) => {
console.log(`编译: ${file.name}`);
// 模拟编译过程
const jsCode = file.content
.replace(/:\s*\w+/g, '') // 移除类型注解
.replace(/interface\s+\w+\s*\{[^}]+\}/g, '') // 移除接口
.replace(/export\s+type\s+\w+/g, '') // 移除类型导出
.trim();
return {
...file,
content: jsCode,
extension: '.js'
};
},
// 打包
bundle: async (files, config) => {
console.log('打包文件...');
const bundleContent = files
.map(file => `// ${file.name}\n${file.content}`)
.join('\n\n');
return {
name: 'bundle.js',
content: bundleContent,
size: bundleContent.length
};
},
// 压缩
minify: async (file, config) => {
console.log('压缩代码...');
// 简单压缩:移除空格和注释
const minified = file.content
.replace(/\/\/.*$/gm, '')
.replace(/\/\*[\s\S]*?\*\//g, '')
.replace(/\s+/g, ' ')
.trim();
return {
...file,
content: minified,
size: minified.length
};
}
};
// 模拟源文件
const sourceFiles = [
{
name: 'math.ts',
content: `
export function add(a: number, b: number): number {
return a + b;
}
export function subtract(a: number, b: number): number {
return a - b;
}
`
},
{
name: 'app.ts',
content: `
import { add } from './math';
export function calculate(): number {
return add(1, 2);
}
`
}
];
// 创建构建管道
const pipeline = new TypeScriptBuildPipeline(tsconfig)
.addStep('类型检查', processors.typeCheck)
.addStep('编译', processors.compile)
.addStep('打包', processors.bundle)
.addStep('压缩', processors.minify);
// 执行构建
pipeline.build(sourceFiles).then(result => {
console.log('构建结果:', result);
});
七、实战应用: 在JavaScript项目中引入TypeScript
渐进式迁移策略
// 7.1 混合项目结构管理
class HybridProjectManager {
constructor(options = {}) {
this.options = {
tsDir: 'src/ts',
jsDir: 'src/js',
buildDir: 'dist',
allowJS: true,
checkJS: true,
...options
};
this.fileRegistry = new Map();
}
// 注册文件
registerFile(path, type) {
this.fileRegistry.set(path, {
type,
dependencies: [],
errors: []
});
// 自动检测文件类型
if (path.endsWith('.ts') || path.endsWith('.tsx')) {
this.fileRegistry.get(path).type = 'typescript';
} else if (path.endsWith('.js') || path.endsWith('.jsx')) {
this.fileRegistry.get(path).type = 'javascript';
}
}
// 分析依赖关系
analyzeDependencies(path) {
const file = this.fileRegistry.get(path);
if (!file) return;
const content = this.readFile(path);
const dependencies = [];
// 解析导入语句
const importRegex = /import\s+(?:.*?from\s+)?['"]([^'"]+)['"]/g;
let match;
while ((match = importRegex.exec(content)) !== null) {
dependencies.push(match[1]);
}
file.dependencies = dependencies;
}
// 检查混合项目问题
checkHybridIssues() {
const issues = [];
for (const [path, file] of this.fileRegistry) {
// 检查TypeScript文件是否导入了未定义的JavaScript模块
if (file.type === 'typescript') {
for (const dep of file.dependencies) {
if (dep.endsWith('.js')) {
const depPath = this.resolvePath(path, dep);
const depFile = this.fileRegistry.get(depPath);
if (depFile && depFile.type === 'javascript') {
issues.push({
type: 'ts-imports-js',
message: `TypeScript文件 ${path} 导入了JavaScript文件 ${depPath}`,
severity: 'warning',
suggestion: '考虑将JavaScript文件迁移为TypeScript或添加类型声明'
});
}
}
}
}
// 检查JavaScript文件是否缺少JSDoc注释
if (file.type === 'javascript' && this.options.checkJS) {
const content = this.readFile(path);
const hasJSDoc = /\/\*\*\s*\n(?:[^*]|\*(?!\/))*\*\//.test(content);
if (!hasJSDoc) {
issues.push({
type: 'missing-jsdoc',
message: `JavaScript文件 ${path} 缺少JSDoc注释`,
severity: 'info',
suggestion: '添加JSDoc注释以提供类型信息'
});
}
}
}
return issues;
}
// 生成迁移建议
generateMigrationPlan() {
const plan = {
phase1: [], // 立即迁移的文件
phase2: [], // 可以稍后迁移的文件
declarations: [] // 需要创建的类型声明文件
};
for (const [path, file] of this.fileRegistry) {
if (file.type === 'javascript') {
// 分析复杂性
const complexity = this.assessComplexity(path);
if (complexity <= 2) {
plan.phase1.push(path);
} else {
plan.phase2.push(path);
}
// 检查是否需要声明文件
if (file.dependencies.some(dep => dep.startsWith('@types/'))) {
plan.declarations.push(path);
}
}
}
return plan;
}
// 评估文件复杂性
assessComplexity(path) {
const content = this.readFile(path);
let score = 0;
// 基于行数
const lines = content.split('\n').length;
if (lines > 100) score += 2;
else if (lines > 50) score += 1;
// 基于函数数量
const functionCount = (content.match(/function\s+\w+|\b\w+\s*=/g) || []).length;
score += Math.min(Math.floor(functionCount / 5), 3);
// 基于外部依赖
const importCount = (content.match(/import\s+|require\(/g) || []).length;
score += Math.min(importCount, 2);
return score;
}
// 工具方法
readFile(path) {
// 模拟文件读取
return '模拟文件内容';
}
resolvePath(base, relative) {
// 简化路径解析
return relative;
}
}
// 使用示例
const manager = new HybridProjectManager({
tsDir: 'src/ts',
jsDir: 'src/js',
checkJS: true
});
// 注册文件
manager.registerFile('src/js/user.js', 'javascript');
manager.registerFile('src/ts/auth.ts', 'typescript');
manager.registerFile('src/js/utils.js', 'javascript');
// 分析问题
const issues = manager.checkHybridIssues();
console.log('发现的问题:', issues);
// 生成迁移计划
const migrationPlan = manager.generateMigrationPlan();
console.log('迁移计划:', migrationPlan);
// 7.2 类型声明生成器
class TypeDeclarationGenerator {
static generateFromJS(jsCode, options = {}) {
const declarations = [];
// 解析函数
const functionRegex = /function\s+(\w+)\s*\(([^)]*)\)/g;
let match;
while ((match = functionRegex.exec(jsCode)) !== null) {
const [, funcName, params] = match;
const paramTypes = this.inferParamTypes(params);
const returnType = this.inferReturnType(jsCode, funcName);
declarations.push(
`declare function ${funcName}(${paramTypes}): ${returnType};`
);
}
// 解析类
const classRegex = /class\s+(\w+)/g;
while ((match = classRegex.exec(jsCode)) !== null) {
const [, className] = match;
const classDeclaration = this.generateClassDeclaration(jsCode, className);
declarations.push(classDeclaration);
}
// 解析变量导出
const exportRegex = /exports\.(\w+)\s*=/g;
while ((match = exportRegex.exec(jsCode)) !== null) {
const [, exportName] = match;
const type = this.inferVariableType(jsCode, exportName);
declarations.push(`declare const ${exportName}: ${type};`);
}
return declarations.join('\n');
}
static inferParamTypes(paramsStr) {
const params = paramsStr.split(',').map(p => p.trim()).filter(p => p);
return params.map((param, index) => {
const [name, defaultValue] = param.split('=').map(s => s.trim());
let type = 'any';
if (defaultValue) {
if (defaultValue.includes("'") || defaultValue.includes('"')) {
type = 'string';
} else if (defaultValue === 'true' || defaultValue === 'false') {
type = 'boolean';
} else if (!isNaN(parseFloat(defaultValue))) {
type = 'number';
} else if (defaultValue === '[]') {
type = 'any[]';
} else if (defaultValue === '{}') {
type = 'object';
}
}
return `${name}: ${type}`;
}).join(', ');
}
static inferReturnType(jsCode, funcName) {
// 简化实现:检查return语句
const returnRegex = new RegExp(`function\\s+${funcName}[^{]*{([^}]*return[^;]+;)?`, 'i');
const match = jsCode.match(returnRegex);
if (match && match[1]) {
const returnExpr = match[1].replace('return', '').trim();
if (returnExpr.includes("'") || returnExpr.includes('"')) {
return 'string';
} else if (returnExpr === 'true' || returnExpr === 'false') {
return 'boolean';
} else if (!isNaN(parseFloat(returnExpr))) {
return 'number';
}
}
return 'any';
}
static generateClassDeclaration(jsCode, className) {
const declaration = [`declare class ${className} {`];
// 提取构造函数
const constructorRegex = new RegExp(`constructor\\(([^)]*)\\)`, 'g');
const constructorMatch = constructorRegex.exec(jsCode);
if (constructorMatch) {
const params = constructorMatch[1];
const paramTypes = this.inferParamTypes(params);
declaration.push(` constructor(${paramTypes});`);
}
// 提取方法
const methodRegex = new RegExp(`${className}\\.prototype\\.(\\w+)\\s*=\\s*function`, 'g');
while ((match = methodRegex.exec(jsCode)) !== null) {
const [, methodName] = match;
declaration.push(` ${methodName}(): any;`);
}
declaration.push('}');
return declaration.join('\n');
}
static inferVariableType(jsCode, varName) {
const regex = new RegExp(`${varName}\\s*=\\s*([^;]+)`, 'g');
const match = regex.exec(jsCode);
if (match) {
const value = match[1].trim();
if (value.startsWith('[')) return 'any[]';
if (value.startsWith('{')) return 'object';
if (value.includes("'") || value.includes('"')) return 'string';
if (value === 'true' || value === 'false') return 'boolean';
if (!isNaN(parseFloat(value))) return 'number';
}
return 'any';
}
}
// 生成类型声明示例
const jsCode = `
function greet(name) {
return 'Hello, ' + name;
}
class User {
constructor(name, age = 18) {
this.name = name;
this.age = age;
}
sayHello() {
return greet(this.name);
}
}
exports.greet = greet;
exports.User = User;
exports.VERSION = '1.0.0';
`;
const declarations = TypeDeclarationGenerator.generateFromJS(jsCode);
console.log('生成的类型声明:');
console.log(declarations);
八、性能优化与最佳实践
TypeScript编译优化
// 8.1 增量编译
class IncrementalCompiler {
constructor() {
this.fileCache = new Map();
this.dependencyGraph = new Map();
this.lastCompileTime = Date.now();
}
// 检查文件是否需要重新编译
needsRecompile(filePath, content) {
const cached = this.fileCache.get(filePath);
if (!cached) {
return true; // 新文件
}
if (cached.content !== content) {
return true; // 内容改变
}
// 检查依赖是否改变
const dependencies = this.dependencyGraph.get(filePath) || [];
for (const dep of dependencies) {
const depCached = this.fileCache.get(dep);
if (!depCached || depCached.timestamp > cached.timestamp) {
return true; // 依赖已更新
}
}
return false; // 无需重新编译
}
// 增量编译
incrementalCompile(files) {
const toCompile = [];
const startTime = Date.now();
for (const file of files) {
if (this.needsRecompile(file.path, file.content)) {
toCompile.push(file);
}
}
console.log(`需要重新编译 ${toCompile.length} 个文件`);
if (toCompile.length === 0) {
console.log('没有文件需要重新编译,使用缓存');
return this.getCachedOutput();
}
// 执行编译
const results = this.compileFiles(toCompile);
// 更新缓存
for (const file of toCompile) {
this.fileCache.set(file.path, {
content: file.content,
timestamp: startTime,
output: results[file.path]
});
}
this.lastCompileTime = startTime;
return results;
}
compileFiles(files) {
// 简化编译过程
const results = {};
for (const file of files) {
results[file.path] = file.content.replace(/:\s*\w+/g, '');
}
return results;
}
getCachedOutput() {
const output = {};
for (const [path, cached] of this.fileCache) {
output[path] = cached.output;
}
return output;
}
}
// 8.2 项目引用优化
class ProjectReferenceOptimizer {
static optimize(config, projects) {
const optimized = { ...config };
// 分析项目依赖
const dependencies = this.analyzeDependencies(projects);
// 设置项目引用
optimized.compilerOptions = {
...optimized.compilerOptions,
composite: true,
declaration: true,
declarationMap: true,
incremental: true
};
optimized.references = dependencies.map(dep => ({ path: dep }));
return optimized;
}
static analyzeDependencies(projects) {
const graph = new Map();
// 构建依赖图
for (const project of projects) {
const deps = this.extractImports(project.source);
graph.set(project.name, deps);
}
// 拓扑排序
return this.topologicalSort(graph);
}
static extractImports(source) {
const imports = [];
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
let match;
while ((match = importRegex.exec(source)) !== null) {
imports.push(match[1]);
}
return imports;
}
static topologicalSort(graph) {
const visited = new Set();
const result = [];
const visit = (node) => {
if (visited.has(node)) return;
visited.add(node);
const dependencies = graph.get(node) || [];
for (const dep of dependencies) {
visit(dep);
}
result.push(node);
};
for (const node of graph.keys()) {
visit(node);
}
return result;
}
}
// 8.3 内存优化
class TypeScriptMemoryOptimizer {
constructor() {
this.memoryCache = new Map();
this.maxCacheSize = 100;
}
// 编译结果缓存
cacheCompilationResult(filePath, ast, diagnostics, output) {
const cacheEntry = {
ast,
diagnostics,
output,
timestamp: Date.now(),
size: this.calculateSize(ast) + this.calculateSize(output)
};
this.memoryCache.set(filePath, cacheEntry);
this.cleanupCache();
}
// 获取缓存结果
getCachedResult(filePath) {
const cached = this.memoryCache.get(filePath);
if (cached) {
// 更新访问时间
cached.timestamp = Date.now();
return cached;
}
return null;
}
// 清理缓存
cleanupCache() {
if (this.memoryCache.size <= this.maxCacheSize) {
return;
}
// LRU缓存清理
const entries = Array.from(this.memoryCache.entries());
entries.sort((a, b) => a[1].timestamp - b[1].timestamp);
const toRemove = entries.slice(0, entries.length - this.maxCacheSize);
for (const [key] of toRemove) {
this.memoryCache.delete(key);
}
}
// 计算对象大小
calculateSize(obj) {
const str = JSON.stringify(obj);
return str.length * 2; // 粗略估计(UTF-16)
}
// AST节点缓存池
createASTNodePool() {
const pool = new Map();
return {
getNode(type, props) {
const key = `${type}:${JSON.stringify(props)}`;
if (pool.has(key)) {
return pool.get(key);
}
const node = { type, ...props };
pool.set(key, node);
return node;
},
clear() {
pool.clear();
},
get size() {
return pool.size;
}
};
}
}
TypeScript最佳实践
// 8.4 代码组织最佳实践
class TypeScriptBestPractices {
static structureProject(projectType) {
const structures = {
library: {
src: [
'index.ts', // 主入口
'types/', // 类型定义
'utils/', // 工具函数
'core/', // 核心逻辑
'tests/' // 测试文件
],
config: [
'tsconfig.json',
'tsconfig.build.json',
'package.json',
'.eslintrc.js'
],
docs: 'README.md'
},
application: {
src: [
'main.ts', // 应用入口
'components/', // 组件
'services/', // 服务层
'models/', // 数据模型
'utils/', // 工具函数
'styles/', // 样式文件
'assets/', // 静态资源
'tests/' // 测试
],
config: [
'tsconfig.json',
'tsconfig.app.json',
'package.json',
'webpack.config.js'
],
public: 'index.html'
},
node: {
src: [
'index.ts', // 应用入口
'controllers/', // 控制器
'services/', // 服务层
'models/', // 数据模型
'middleware/', // 中间件
'routes/', // 路由
'utils/', // 工具函数
'tests/' // 测试
],
config: [
'tsconfig.json',
'package.json',
'.env',
'dockerfile'
]
}
};
return structures[projectType] || structures.library;
}
static namingConventions = {
interfaces: {
rule: '使用 PascalCase,以 I 开头',
examples: ['IUser', 'IProductService', 'IRepository']
},
types: {
rule: '使用 PascalCase',
examples: ['UserData', 'ApiResponse', 'ConfigOptions']
},
classes: {
rule: '使用 PascalCase',
examples: ['UserService', 'DatabaseConnection', 'HttpClient']
},
variables: {
rule: '使用 camelCase',
examples: ['userName', 'productList', 'isLoading']
},
constants: {
rule: '使用 UPPER_SNAKE_CASE',
examples: ['MAX_RETRY_COUNT', 'API_BASE_URL', 'DEFAULT_TIMEOUT']
},
generics: {
rule: '使用单个大写字母,T 开头',
examples: ['T', 'K', 'V', 'TKey', 'TValue']
}
};
static createTSConfig(projectType, options = {}) {
const baseConfig = {
compilerOptions: {
target: 'es2020',
module: 'commonjs',
lib: ['es2020'],
outDir: './dist',
rootDir: './src',
strict: true,
esModuleInterop: true,
skipLibCheck: true,
forceConsistentCasingInFileNames: true
}
};
const typeSpecific = {
library: {
compilerOptions: {
declaration: true,
declarationMap: true,
sourceMap: true
}
},
application: {
compilerOptions: {
jsx: 'react-jsx',
moduleResolution: 'node',
allowSyntheticDefaultImports: true
}
},
node: {
compilerOptions: {
module: 'commonjs',
target: 'es2020',
lib: ['es2020']
}
}
};
return this.deepMerge(
baseConfig,
typeSpecific[projectType] || {},
{ compilerOptions: options }
);
}
static deepMerge(...objects) {
return objects.reduce((acc, obj) => {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
if (this.isObject(obj[key]) && this.isObject(acc[key])) {
acc[key] = this.deepMerge(acc[key], obj[key]);
} else {
acc[key] = obj[key];
}
}
}
return acc;
}, {});
}
static isObject(item) {
return item && typeof item === 'object' && !Array.isArray(item);
}
// 错误处理最佳实践
static errorHandlingPatterns = {
// 使用Result类型处理错误
Result: `
type Result<T, E = Error> =
| { success: true; data: T }
| { success: false; error: E };
function safeOperation(): Result<string> {
try {
const result = riskyOperation();
return { success: true, data: result };
} catch (error) {
return { success: false, error: error as Error };
}
}
`,
// 自定义错误类
CustomError: `
class AppError extends Error {
constructor(
message: string,
public code: string,
public statusCode: number = 500
) {
super(message);
this.name = 'AppError';
}
}
class ValidationError extends AppError {
constructor(message: string) {
super(message, 'VALIDATION_ERROR', 400);
this.name = 'ValidationError';
}
}
`,
// 错误边界
ErrorBoundary: `
class ErrorBoundary {
private errorHandlers = new Map<string, (error: Error) => void>();
register(component: string, handler: (error: Error) => void) {
this.errorHandlers.set(component, handler);
}
handle(component: string, error: Error) {
const handler = this.errorHandlers.get(component);
if (handler) {
handler(error);
} else {
console.error(\`未处理的错误 (\${component}):\`, error);
}
}
}
`
};
}
// 使用最佳实践
console.log('库项目结构:', TypeScriptBestPractices.structureProject('library'));
console.log('命名约定:', TypeScriptBestPractices.namingConventions);
const libConfig = TypeScriptBestPractices.createTSConfig('library', {
outDir: './lib',
declarationDir: './types'
});
console.log('库TS配置:', JSON.stringify(libConfig, null, 2));
总结
TypeScript通过强大的类型系统、接口泛型、装饰器等特性,极大地提升了JavaScript代码的质量和开发体验。本文深入探讨了TypeScript的核心实现原理和高级特性,并提供了实际可用的代码示例。
核心要点总结:
-
类型系统: TypeScript通过编译时类型检查提供安全保障,运行时也可通过代理模式实现类型验证
-
接口与泛型: 通过设计模式模拟接口实现,泛型提供代码复用性和类型安全性
-
装饰器: 元编程的强大工具,实现依赖注入、验证、日志等横切关注点
-
类型推断: 自动推断变量类型,减少冗余的类型注解
-
模块与工程化: 完善的模块系统支持,与构建工具深度集成
-
最佳实践: 合理的项目结构、命名约定和错误处理策略
TypeScript不仅是JavaScript的类型超集,更是一种工程化实践。它将静态类型语言的严谨性与JavaScript的灵活性完美结合,成为现代前端开发不可或缺的工具。随着TypeScript的持续发展,其类型系统将变得更加智能和强大,为构建大型、可维护的应用程序提供坚实保障。
在实际项目中,应根据团队规模、项目复杂度和技术栈选择合适的TypeScript特性,平衡类型安全性和开发效率。通过渐进式迁移策略,即使现有JavaScript项目也能平滑过渡到TypeScript,享受类型系统带来的诸多好处。