一文看懂--什么是typescript

/**

  • ========================================
  • TypeScript 完整教程:从入门到精通
  • ========================================
  • 目录:
    1. TypeScript 基础
    1. 基本类型
    1. 接口 (Interface)
    1. 类 (Class)
    1. 函数
    1. 泛型 (Generics)
    1. 高级类型
    1. 类型守卫和类型断言
    1. 装饰器 (Decorators)
    1. 模块和命名空间
    1. 实战项目示例
      */

// ========================================
// 1. TypeScript 基础
// ========================================

/**

  • TypeScript 是 JavaScript 的超集,添加了静态类型系统
  • 编译后生成纯 JavaScript 代码
    */

// 变量声明
let message: string = "Hello TypeScript";
let count: number = 42;
let isActive: boolean = true;

// 类型推断 - TypeScript 可以自动推断类型
let inferredString = "这是字符串"; // 自动推断为 string
let inferredNumber = 100; // 自动推断为 number

// ========================================
// 2. 基本类型
// ========================================

// 2.1 基础类型
let str: string = "文本";
let num: number = 123;
let bool: boolean = false;
let u: undefined = undefined;
let n: null = null;

// 2.2 数组类型
let arr1: number[] = [1, 2, 3];
let arr2: Array = ["a", "b", "c"];
let arr3: (string | number)[] = [1, "2", 3]; // 联合类型数组

// 2.3 元组 (Tuple) - 固定长度和类型的数组
let tuple: [string, number, boolean] = ["hello", 42, true];
console.log(tuple[0]); // "hello"

// 2.4 枚举 (Enum)
enum Color {
Red, // 0
Green, // 1
Blue // 2
}
let c: Color = Color.Green;

enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}

// 2.5 Any 类型 - 关闭类型检查
let anything: any = 42;
anything = "字符串";
anything = true;

// 2.6 Unknown 类型 - 更安全的 any
let uncertain: unknown = 4;
// uncertain.toFixed(); // 错误:必须先进行类型检查
if (typeof uncertain === "number") {
uncertain.toFixed(2); // 正确
}

// 2.7 Void 类型 - 通常用于函数无返回值
function logMessage(msg: string): void {
console.log(msg);
}

// 2.8 Never 类型 - 永远不会返回
function throwError(message: string): never {
throw new Error(message);
}

// 2.9 Object 类型
let obj: object = { name: "张三" };
let specificObj: { name: string; age: number } = {
name: "李四",
age: 25
};

// ========================================
// 3. 接口 (Interface)
// ========================================

// 3.1 基本接口
interface User {
id: number;
name: string;
email: string;
}

const user1: User = {
id: 1,
name: "张三",
email: "zhangsan@example.com"
};

// 3.2 可选属性
interface Product {
id: number;
name: string;
description?: string; // 可选属性
price: number;
}

// 3.3 只读属性
interface Point {
readonly x: number;
readonly y: number;
}

let p1: Point = { x: 10, y: 20 };
// p1.x = 5; // 错误:只读属性

// 3.4 函数类型接口
interface SearchFunc {
(source: string, subString: string): boolean;
}

const mySearch: SearchFunc = (src, sub) => {
return src.includes(sub);
};

// 3.5 索引签名
interface StringArray {
[index: number]: string;
}

let myArray: StringArray = ["Bob", "Alice"];

interface Dictionary {
[key: string]: number;
}

let scores: Dictionary = {
math: 95,
english: 88
};

// 3.6 接口继承
interface Shape {
color: string;
}

interface Square extends Shape {
sideLength: number;
}

let square: Square = {
color: "blue",
sideLength: 10
};

// 3.7 混合类型接口
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}

function getCounter(): Counter {
let counter = function(start: number) {
return Started at ${start};
} as Counter;

counter.interval = 123;
counter.reset = function() {
console.log("Reset");
};

return counter;
}

// ========================================
// 4. 类 (Class)
// ========================================

// 4.1 基本类
class Animal {
name: string;

constructor(name: string) {
this.name = name;
}

move(distance: number = 0): void {
console.log(${this.name} 移动了 ${distance} 米);
}
}

const dog = new Animal("旺财");
dog.move(10);

// 4.2 继承
class Dog extends Animal {
breed: string;

constructor(name: string, breed: string) {
super(name); // 调用父类构造函数
this.breed = breed;
}

bark(): void {
console.log("汪汪汪!");
}

// 重写父类方法
move(distance: number = 5): void {
console.log("跑步中...");
super.move(distance);
}
}

// 4.3 访问修饰符
class Person {
public name: string; // 公共属性(默认)
private age: number; // 私有属性
protected gender: string; // 受保护属性
readonly id: number; // 只读属性

constructor(name: string, age: number, gender: string, id: number) {
this.name = name;
this.age = age;
this.gender = gender;
this.id = id;
}

public getAge(): number {
return this.age;
}

private calculateBirthYear(): number {
return new Date().getFullYear() - this.age;
}
}

// 4.4 Getter 和 Setter
class Employee {
private _salary: number = 0;

get salary(): number {
return this._salary;
}

set salary(value: number) {
if (value < 0) {
throw new Error("薪资不能为负数");
}
this._salary = value;
}
}

// 4.5 静态成员
class MathUtil {
static PI: number = 3.14159;

static calculateCircleArea(radius: number): number {
return this.PI * radius * radius;
}
}

console.log(MathUtil.PI);
console.log(MathUtil.calculateCircleArea(5));

// 4.6 抽象类
abstract class Department {
abstract name: string;

constructor(public departmentId: number) {}

abstract printMeeting(): void;

printName(): void {
console.log(部门: ${this.name});
}
}

class AccountingDepartment extends Department {
name: string = "会计部";

printMeeting(): void {
console.log("会计部门会议在早上 10 点");
}
}

// ========================================
// 5. 函数
// ========================================

// 5.1 函数类型
function add(x: number, y: number): number {
return x + y;
}

// 5.2 可选参数和默认参数
function buildName(firstName: string, lastName?: string): string {
if (lastName) {
return ${firstName} ${lastName};
}
return firstName;
}

function greet(name: string, greeting: string = "你好"): string {
return ${greeting}, ${name}!;
}

// 5.3 剩余参数
function sum(...numbers: number[]): number {
return numbers.reduce((acc, curr) => acc + curr, 0);
}

console.log(sum(1, 2, 3, 4, 5)); // 15

// 5.4 函数重载
function reverse(x: string): string;
function reverse(x: number): number;
function reverse(x: string | number): string | number {
if (typeof x === "string") {
return x.split("").reverse().join("");
}
return Number(x.toString().split("").reverse().join(""));
}

console.log(reverse("hello")); // "olleh"
console.log(reverse(12345)); // 54321

// 5.5 箭头函数
const multiply = (a: number, b: number): number => a * b;

// 5.6 this 参数
interface Card {
suit: string;
card: number;
}

interface Deck {
suits: string[];
cards: number[];
createCardPicker(this: Deck): () => Card;
}

const deck: Deck = {
suits: ["红心", "方块", "梅花", "黑桃"],
cards: Array(52).fill(0).map((_, i) => i),

createCardPicker: function(this: Deck) {
return () => {
const pickedCard = Math.floor(Math.random() * 52);
const pickedSuit = Math.floor(pickedCard / 13);

return {
suit: this.suits[pickedSuit],
card: pickedCard % 13
};
};
}
};

// ========================================
// 6. 泛型 (Generics)
// ========================================

// 6.1 泛型函数
function identity(arg: T): T {
return arg;
}

let output1 = identity("hello");
let output2 = identity(42);
let output3 = identity("自动推断"); // 类型推断

// 6.2 泛型数组
function loggingIdentity(arg: T[]): T[] {
console.log(arg.length);
return arg;
}

// 6.3 泛型接口
interface GenericIdentityFn {
(arg: T): T;
}

let myIdentity: GenericIdentityFn = identity;

// 6.4 泛型类
class GenericNumber {
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(0, (x, y) => x + y);

// 6.5 泛型约束
interface Lengthwise {
length: number;
}

function logLength(arg: T): T {
console.log(arg.length);
return arg;
}

logLength("hello"); // 正确
logLength([1, 2, 3]); // 正确
// logLength(123); // 错误:number 没有 length 属性

// 6.6 在泛型约束中使用类型参数
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}

let person = { name: "张三", age: 30 };
let personName = getProperty(person, "name"); // 正确
// let invalid = getProperty(person, "unknown"); // 错误

// 6.7 泛型工具类型
interface Todo {
title: string;
description: string;
completed: boolean;
}

// Partial - 所有属性变为可选
type PartialTodo = Partial;

// Required - 所有属性变为必选
type RequiredTodo = Required;

// Readonly - 所有属性变为只读
type ReadonlyTodo = Readonly;

// Pick - 选择部分属性
type TodoPreview = Pick<Todo, "title" | "completed">;

// Omit - 排除部分属性
type TodoWithoutDescription = Omit<Todo, "description">;

// Record - 构造对象类型
type PageInfo = Record<"home" | "about" | "contact", { title: string }>;

// ========================================
// 7. 高级类型
// ========================================

// 7.1 联合类型
type StringOrNumber = string | number;

function printId(id: StringOrNumber): void {
console.log(ID: ${id});
}

// 7.2 交叉类型
interface Colorful {
color: string;
}

interface Circle {
radius: number;
}

type ColorfulCircle = Colorful & Circle;

const cc: ColorfulCircle = {
color: "红色",
radius: 10
};

// 7.3 类型别名
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;

// 7.4 字面量类型
type Direction2 = "north" | "south" | "east" | "west";

function move2(direction: Direction2): void {
console.log(向 ${direction} 移动);
}

// 7.5 类型索引
interface PersonInfo {
name: string;
age: number;
location: string;
}

type PersonKeys = keyof PersonInfo; // "name" | "age" | "location"

// 7.6 映射类型
type Nullable = {
[P in keyof T]: T[P] | null;
};

type NullablePerson = Nullable;

// 7.7 条件类型
type IsString = T extends string ? true : false;

type A = IsString; // true
type B = IsString; // false

// 7.8 infer 关键字
type ReturnType2 = T extends (...args: any[]) => infer R ? R : any;

function getUser() {
return { name: "张三", age: 25 };
}

type UserReturnType = ReturnType2;

// ========================================
// 8. 类型守卫和类型断言
// ========================================

// 8.1 typeof 类型守卫
function padLeft(value: string, padding: string | number): string {
if (typeof padding === "number") {
return " ".repeat(padding) + value;
}
return padding + value;
}

// 8.2 instanceof 类型守卫
class Bird {
fly(): void {
console.log("鸟在飞");
}
}

class Fish {
swim(): void {
console.log("鱼在游");
}
}

function move3(animal: Bird | Fish): void {
if (animal instanceof Bird) {
animal.fly();
} else {
animal.swim();
}
}

// 8.3 自定义类型守卫
interface Cat {
meow(): void;
}

interface Dog2 {
bark(): void;
}

function isCat(pet: Cat | Dog2): pet is Cat {
return (pet as Cat).meow !== undefined;
}

function makeSound(pet: Cat | Dog2): void {
if (isCat(pet)) {
pet.meow();
} else {
pet.bark();
}
}

// 8.4 类型断言
let someValue: unknown = "这是一个字符串";
let strLength1: number = (someValue as string).length;
let strLength2: number = (someValue).length; // JSX 中不可用

// 8.5 非空断言
function processValue(value: string | null): void {
console.log(value!.toUpperCase()); // 断言 value 不为 null
}

// 8.6 as const 断言
const config = {
host: "localhost",
port: 8080
} as const; // 所有属性变为只读字面量类型

// ========================================
// 9. 装饰器 (Decorators)
// ========================================

// 注意:需要在 tsconfig.json 中启用 experimentalDecorators

// 9.1 类装饰器
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};
}
}

// 9.2 方法装饰器
function enumerable(value: boolean) {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
descriptor.enumerable = value;
};
}

class Calculator {
@enumerable(false)
calculate(x: number, y: number): number {
return x + y;
}
}

// 9.3 属性装饰器
function format(formatString: string) {
return function (target: any, propertyKey: string) {
let value: string;

const getter = function() {
return value;
};

const setter = function(newVal: string) {
value = formatString.replace("{value}", newVal);
};

Object.defineProperty(target, propertyKey, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
};
}

class FormattedGreeting {
@format("Hello, {value}!")
greeting: string;
}

// ========================================
// 10. 模块和命名空间
// ========================================

// 10.1 模块导出
// export const PI = 3.14;
// export function calculateArea(radius: number): number {
// return PI * radius * radius;
// }

// export default class Circle {
// constructor(public radius: number) {}
// }

// 10.2 模块导入
// import Circle, { PI, calculateArea } from './circle';
// import * as MathLib from './mathLib';

// 10.3 命名空间
namespace Validation {
export interface StringValidator {
isValid(s: string): boolean;
}

export class EmailValidator implements StringValidator {
isValid(s: string): boolean {
const emailRegex = /[\s@]+@[\s@]+.[\s@]+$/;
return emailRegex.test(s);
}
}

export class PhoneValidator implements StringValidator {
isValid(s: string): boolean {
const phoneRegex = /^\d{11}$/;
return phoneRegex.test(s);
}
}
}

const emailValidator = new Validation.EmailValidator();
console.log(emailValidator.isValid("test@example.com")); // true

// ========================================
// 11. 实战项目示例
// ========================================

// 11.1 用户管理系统
interface IUser {
id: number;
username: string;
email: string;
role: "admin" | "user" | "guest";
createdAt: Date;
}

interface IUserRepository {
create(user: Omit<IUser, "id" | "createdAt">): IUser;
findById(id: number): IUser | undefined;
findAll(): IUser[];
update(id: number, user: Partial): IUser | undefined;
delete(id: number): boolean;
}

class UserRepository implements IUserRepository {
private users: IUser[] = [];
private nextId: number = 1;

create(userData: Omit<IUser, "id" | "createdAt">): IUser {
const newUser: IUser = {
id: this.nextId++,
...userData,
createdAt: new Date()
};
this.users.push(newUser);
return newUser;
}

findById(id: number): IUser | undefined {
return this.users.find(user => user.id === id);
}

findAll(): IUser[] {
return [...this.users];
}

update(id: number, userData: Partial): IUser | undefined {
const userIndex = this.users.findIndex(user => user.id === id);
if (userIndex === -1) return undefined;

this.users[userIndex] = {
...this.users[userIndex],
...userData
};
return this.users[userIndex];
}

delete(id: number): boolean {
const userIndex = this.users.findIndex(user => user.id === id);
if (userIndex === -1) return false;

this.users.splice(userIndex, 1);
return true;
}
}

// 11.2 API 响应类型
interface ApiResponse {
success: boolean;
data?: T;
error?: string;
timestamp: number;
}

class ApiClient {
async fetchData(url: string): Promise<ApiResponse> {
try {
// 模拟 API 请求
const data = {} as T;
return {
success: true,
data,
timestamp: Date.now()
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : "未知错误",
timestamp: Date.now()
};
}
}
}

// 11.3 事件发射器
type EventCallback<T = any> = (data: T) => void;

class EventEmitter {
private events: Map<string, EventCallback[]> = new Map();

on(event: string, callback: EventCallback): void {
if (!this.events.has(event)) {
this.events.set(event, []);
}
this.events.get(event)!.push(callback);
}

off(event: string, callback: EventCallback): void {
const callbacks = this.events.get(event);
if (callbacks) {
const index = callbacks.indexOf(callback);
if (index > -1) {
callbacks.splice(index, 1);
}
}
}

emit(event: string, data: T): void {
const callbacks = this.events.get(event);
if (callbacks) {
callbacks.forEach(callback => callback(data));
}
}
}

// 11.4 状态管理
interface State {
count: number;
user: IUser | null;
loading: boolean;
}

type Action =
| { type: "INCREMENT" }
| { type: "DECREMENT" }
| { type: "SET_USER"; payload: IUser }
| { type: "SET_LOADING"; payload: boolean };

class Store {
private state: State = {
count: 0,
user: null,
loading: false
};

private listeners: Array<(state: State) => void> = [];

getState(): Readonly {
return { ...this.state };
}

dispatch(action: Action): void {
this.state = this.reducer(this.state, action);
this.notify();
}

subscribe(listener: (state: State) => void): () => void {
this.listeners.push(listener);
return () => {
const index = this.listeners.indexOf(listener);
if (index > -1) {
this.listeners.splice(index, 1);
}
};
}

private reducer(state: State, action: Action): State {
switch (action.type) {
case "INCREMENT":
return { ...state, count: state.count + 1 };
case "DECREMENT":
return { ...state, count: state.count - 1 };
case "SET_USER":
return { ...state, user: action.payload };
case "SET_LOADING":
return { ...state, loading: action.payload };
default:
return state;
}
}

private notify(): void {
this.listeners.forEach(listener => listener(this.getState()));
}
}

// 使用示例
const userRepo = new UserRepository();
const user1Example = userRepo.create({
username: "zhangsan",
email: "zhangsan@example.com",
role: "user"
});
console.log("创建的用户:", user1Example);

const store = new Store();
const unsubscribe = store.subscribe((state) => {
console.log("状态更新:", state);
});

store.dispatch({ type: "INCREMENT" });
store.dispatch({ type: "SET_USER", payload: user1Example });

/**

  • ========================================
  • 总结与最佳实践
  • ========================================
    1. 始终启用严格模式 (strict: true)
    1. 优先使用 interface 而不是 type(除非需要联合类型)
    1. 避免使用 any,使用 unknown 替代
    1. 善用类型推断,减少冗余类型注解
    1. 使用 readonly 保护不可变数据
    1. 合理使用泛型提高代码复用性
    1. 利用工具类型简化类型操作
    1. 使用类型守卫确保运行时类型安全
    1. 模块化组织代码,避免命名冲突
    1. 编写清晰的类型文档和注释
      */

// 导出示例
export {
UserRepository,
ApiClient,
EventEmitter,
Store
};

posted @ 2026-07-10 10:42  crockery  阅读(2)  评论(0)    收藏  举报