轩辕李的博客 轩辕李的博客
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • HTML&CSS
  • JavaScript
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

轩辕李

勇猛精进,星辰大海
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • HTML&CSS
  • JavaScript
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • JavaScript

  • TypeScript

    • TypeScript极简入门
      • 一、TypeScript 简介
        • 什么是 TypeScript
        • 为什么使用 TypeScript
        • 安装与配置
        • Hello TypeScript
      • 二、基础类型
        • 基本类型
        • 类型推断
        • 联合类型
        • 类型别名
        • 字面量类型
      • 三、接口(Interface)
        • 对象类型
        • 可选属性
        • 只读属性
        • 函数类型
        • 可索引类型
        • 继承接口
      • 四、函数
        • 函数类型
        • 可选参数和默认参数
        • 剩余参数
        • 函数重载
      • 五、类(Class)
        • 基本类
        • 访问修饰符
        • 简写形式
        • 只读属性
        • Getter 和 Setter
        • 静态成员
        • 抽象类
        • 继承
      • 六、泛型(Generics)
        • 泛型函数
        • 泛型数组
        • 泛型接口
        • 泛型类
        • 泛型约束
        • 多个类型参数
      • 七、枚举(Enum)
        • 数字枚举
        • 字符串枚举
        • 常量枚举
      • 八、类型断言
        • as 语法
        • 尖括号语法
        • 非空断言
      • 九、类型守卫
        • typeof 类型守卫
        • instanceof 类型守卫
        • in 类型守卫
        • 自定义类型守卫
      • 十、工具类型
        • Partial(可选)
        • Required(必需)
        • Readonly(只读)
        • Pick(选取)
        • Omit(排除)
        • Record(记录)
      • 十一、模块
        • 导出
        • 导入
      • 十二、命名空间
      • 十三、配置与编译
        • tsconfig.json 常用选项
        • 编译命令
      • 十四、实用技巧
        • 类型推断技巧
        • 常量断言
        • 索引签名
        • 映射类型
      • 十五、总结
    • TypeScript高级特性详解
  • Node.js

  • Vue.js

  • 工程化

  • 浏览器与Web API

  • 前端
  • TypeScript
轩辕李
2025-05-01
目录

TypeScript极简入门

TypeScript 是 JavaScript 的超集,添加了静态类型系统和其他高级特性。本文面向已有 JavaScript 基础的开发者,快速介绍 TypeScript 的核心语法和常用特性。

# 一、TypeScript 简介

# 什么是 TypeScript

TypeScript 是由微软开发的开源编程语言,于 2012 年发布。它在 JavaScript 的基础上添加了:

  • 静态类型系统:编译时类型检查,减少运行时错误
  • 面向对象特性:接口、枚举、泛型、装饰器等
  • 现代 JavaScript 特性:支持最新的 ES 标准
  • 工具支持:强大的 IDE 智能提示和重构能力

TypeScript 与 JavaScript 的关系:

  • TypeScript 是 JavaScript 的超集,所有 JavaScript 代码都是有效的 TypeScript 代码
  • TypeScript 编译后生成纯 JavaScript,可在任何 JavaScript 环境中运行
  • 如果你需要复习 JavaScript 基础,可以参考 JavaScript极简入门

# 为什么使用 TypeScript

  1. 类型安全:编译时发现错误,减少运行时 bug
  2. 更好的 IDE 支持:智能提示、自动补全、重构
  3. 可读性强:类型注解让代码自文档化
  4. 易于维护:大型项目中类型系统提供可靠的代码重构支持
  5. 渐进式采用:可以逐步将 JavaScript 项目迁移到 TypeScript

# 安装与配置

# 全局安装 TypeScript
npm install -g typescript

# 查看版本
tsc --version

# 初始化 TypeScript 项目
tsc --init

这会生成 tsconfig.json 配置文件:

{
  "compilerOptions": {
    "target": "ES2020",           // 编译目标
    "module": "commonjs",         // 模块系统
    "lib": ["ES2020"],            // 包含的库
    "outDir": "./dist",           // 输出目录
    "rootDir": "./src",           // 源码目录
    "strict": true,               // 严格模式
    "esModuleInterop": true,      // ES 模块互操作
    "skipLibCheck": true,         // 跳过库文件检查
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

# Hello TypeScript

创建 hello.ts:

function greet(name: string): string {
    return `Hello, ${name}!`;
}

const message = greet('TypeScript');
console.log(message);

编译并运行:

tsc hello.ts        # 生成 hello.js
node hello.js       # 运行

# 或使用 ts-node 直接运行
npm install -g ts-node
ts-node hello.ts

# 二、基础类型

# 基本类型

// 布尔值
let isDone: boolean = false;

// 数字
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;

// 字符串
let color: string = "blue";
let fullName: string = `Bob Smith`;
let sentence: string = `Hello, my name is ${fullName}`;

// 数组
let list1: number[] = [1, 2, 3];
let list2: Array<number> = [1, 2, 3];  // 泛型写法

// 元组(固定长度和类型的数组)
let tuple: [string, number];
tuple = ['hello', 10];  // 正确
// tuple = [10, 'hello'];  // 错误

// 枚举
enum Color {
    Red,
    Green,
    Blue
}
let c: Color = Color.Green;

// any(任意类型,慎用)
let notSure: any = 4;
notSure = "maybe a string";
notSure = false;

// unknown(类型安全的 any)
let value: unknown = 4;
value = "string";
// let str: string = value;  // 错误:需要类型断言
let str: string = value as string;  // 正确

// void(无返回值)
function warnUser(): void {
    console.log("Warning!");
}

// null 和 undefined
let u: undefined = undefined;
let n: null = null;

// never(永不返回)
function error(message: string): never {
    throw new Error(message);
}

// object
let obj: object = { name: 'Alice' };

# 类型推断

TypeScript 可以自动推断类型:

let num = 5;         // 推断为 number
let str = "hello";   // 推断为 string
let arr = [1, 2, 3]; // 推断为 number[]

// num = "error";    // 错误:不能将 string 赋值给 number

# 联合类型

变量可以是多种类型之一:

let value: string | number;
value = "hello";  // 正确
value = 42;       // 正确
// value = true;  // 错误

function printId(id: number | string) {
    console.log(`Your ID is: ${id}`);
}

printId(101);      // 正确
printId("202");    // 正确

# 类型别名

type ID = number | string;

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

// 复杂类型别名
type User = {
    id: ID;
    name: string;
    age: number;
};

const user: User = {
    id: 1,
    name: 'Alice',
    age: 30
};

# 字面量类型

let direction: "up" | "down" | "left" | "right";
direction = "up";    // 正确
// direction = "top"; // 错误

type Status = "pending" | "success" | "error";
let status: Status = "pending";

// 数字字面量
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;
let roll: DiceRoll = 3;

# 三、接口(Interface)

# 对象类型

interface User {
    id: number;
    name: string;
    email: string;
}

const user: User = {
    id: 1,
    name: 'Alice',
    email: 'alice@example.com'
};

# 可选属性

interface User {
    id: number;
    name: string;
    email?: string;  // 可选属性
}

const user1: User = { id: 1, name: 'Alice' };  // 正确
const user2: User = { id: 2, name: 'Bob', email: 'bob@example.com' };  // 正确

# 只读属性

interface Point {
    readonly x: number;
    readonly y: number;
}

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

# 函数类型

interface SearchFunc {
    (source: string, subString: string): boolean;
}

const mySearch: SearchFunc = function(src, sub) {
    return src.indexOf(sub) > -1;
};

console.log(mySearch('hello world', 'world'));  // true

# 可索引类型

interface StringArray {
    [index: number]: string;
}

const myArray: StringArray = ["Bob", "Alice"];
const myStr: string = myArray[0];

// 字典类型
interface StringDictionary {
    [key: string]: string;
}

const dict: StringDictionary = {
    name: 'Alice',
    city: 'Beijing'
};

# 继承接口

interface Shape {
    color: string;
}

interface Square extends Shape {
    sideLength: number;
}

const square: Square = {
    color: 'blue',
    sideLength: 10
};

// 多重继承
interface PenStroke {
    penWidth: number;
}

interface Square extends Shape, PenStroke {
    sideLength: number;
}

# 四、函数

# 函数类型

// 函数声明
function add(x: number, y: number): number {
    return x + y;
}

// 函数表达式
const multiply = function(x: number, y: number): number {
    return x * y;
};

// 箭头函数
const subtract = (x: number, y: number): number => x - y;

// 完整函数类型
let myAdd: (x: number, y: number) => number = function(x, y) {
    return x + y;
};

# 可选参数和默认参数

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

console.log(buildName('Bob'));           // 'Bob'
console.log(buildName('Bob', 'Smith'));  // 'Bob Smith'

// 默认参数
function greet(name: string, greeting: string = 'Hello'): string {
    return `${greeting}, ${name}!`;
}

console.log(greet('Alice'));              // 'Hello, Alice!'
console.log(greet('Alice', 'Hi'));        // 'Hi, Alice!'

# 剩余参数

function sum(...numbers: number[]): number {
    return numbers.reduce((total, n) => total + n, 0);
}

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

# 函数重载

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('');
    } else {
        return Number(x.toString().split('').reverse().join(''));
    }
}

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

# 五、类(Class)

# 基本类

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}, ${this.age} years old.`;
    }
}

const alice = new Person('Alice', 30);
console.log(alice.greet());

# 访问修饰符

class Person {
    public name: string;      // 公共(默认)
    private age: number;      // 私有
    protected gender: string; // 受保护

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

    getAge(): number {
        return this.age;  // 类内部可访问
    }
}

const person = new Person('Alice', 30, 'female');
console.log(person.name);     // 正确:public
// console.log(person.age);   // 错误:private
console.log(person.getAge()); // 正确:通过方法访问

# 简写形式

class Person {
    constructor(
        public name: string,
        private age: number,
        protected gender: string
    ) {}  // 自动创建并初始化属性

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

# 只读属性

class Person {
    readonly id: number;
    name: string;

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

const person = new Person(1, 'Alice');
// person.id = 2;  // 错误:只读属性

# Getter 和 Setter

class Person {
    private _age: number = 0;

    get age(): number {
        return this._age;
    }

    set age(value: number) {
        if (value < 0) {
            throw new Error('Age cannot be negative');
        }
        this._age = value;
    }
}

const person = new Person();
person.age = 30;          // 调用 setter
console.log(person.age);  // 调用 getter

# 静态成员

class MathUtil {
    static PI: number = 3.14159;

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

console.log(MathUtil.PI);              // 3.14159
console.log(MathUtil.circleArea(5));   // 78.53975

# 抽象类

abstract class Animal {
    abstract makeSound(): void;  // 抽象方法

    move(): void {
        console.log('Moving...');
    }
}

class Dog extends Animal {
    makeSound(): void {
        console.log('Woof!');
    }
}

const dog = new Dog();
dog.makeSound();  // 'Woof!'
dog.move();       // 'Moving...'

// const animal = new Animal();  // 错误:不能实例化抽象类

# 继承

class Animal {
    name: string;

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

    move(distance: number = 0): void {
        console.log(`${this.name} moved ${distance}m.`);
    }
}

class Dog extends Animal {
    constructor(name: string) {
        super(name);  // 调用父类构造函数
    }

    bark(): void {
        console.log('Woof!');
    }

    move(distance: number = 5): void {
        console.log('Running...');
        super.move(distance);  // 调用父类方法
    }
}

const dog = new Dog('Rex');
dog.bark();     // 'Woof!'
dog.move(10);   // 'Running...' 'Rex moved 10m.'

# 六、泛型(Generics)

# 泛型函数

// 不使用泛型
function identity(arg: number): number {
    return arg;
}

// 使用泛型
function identity<T>(arg: T): T {
    return arg;
}

const num = identity<number>(42);
const str = identity<string>('hello');
const bool = identity(true);  // 类型推断

# 泛型数组

function loggingIdentity<T>(arg: T[]): T[] {
    console.log(arg.length);
    return arg;
}

loggingIdentity([1, 2, 3]);
loggingIdentity(['a', 'b', 'c']);

# 泛型接口

interface GenericIdentityFn<T> {
    (arg: T): T;
}

const myIdentity: GenericIdentityFn<number> = function(arg) {
    return arg;
};

console.log(myIdentity(42));

# 泛型类

class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;

    constructor(zeroValue: T, add: (x: T, y: T) => T) {
        this.zeroValue = zeroValue;
        this.add = add;
    }
}

const myGenericNumber = new GenericNumber<number>(
    0,
    (x, y) => x + y
);

console.log(myGenericNumber.add(5, 3));  // 8

# 泛型约束

interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);  // 现在可以访问 length
    return arg;
}

loggingIdentity('hello');         // 正确:string 有 length
loggingIdentity([1, 2, 3]);       // 正确:array 有 length
// loggingIdentity(3);            // 错误:number 没有 length

# 多个类型参数

function pair<T, U>(first: T, second: U): [T, U] {
    return [first, second];
}

const p1 = pair<number, string>(1, 'one');
const p2 = pair(2, 'two');  // 类型推断

# 七、枚举(Enum)

# 数字枚举

enum Direction {
    Up,      // 0
    Down,    // 1
    Left,    // 2
    Right    // 3
}

let dir: Direction = Direction.Up;
console.log(dir);  // 0

// 指定起始值
enum Status {
    Pending = 1,
    Success,      // 2
    Error         // 3
}

# 字符串枚举

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

console.log(Direction.Up);  // "UP"

# 常量枚举

const enum Color {
    Red,
    Green,
    Blue
}

let c: Color = Color.Green;  // 编译后直接替换为数字

# 八、类型断言

# as 语法

let someValue: unknown = "this is a string";
let strLength: number = (someValue as string).length;

# 尖括号语法

let someValue: unknown = "this is a string";
let strLength: number = (<string>someValue).length;

注意:在 JSX 中只能使用 as 语法。

# 非空断言

function liveDangerously(x?: number | null) {
    console.log(x!.toFixed());  // 断言 x 不为 null/undefined
}

liveDangerously(42);  // 正确
// liveDangerously(null);  // 运行时错误

# 九、类型守卫

# typeof 类型守卫

function printValue(value: string | number) {
    if (typeof value === "string") {
        console.log(value.toUpperCase());  // value 被推断为 string
    } else {
        console.log(value.toFixed(2));     // value 被推断为 number
    }
}

# instanceof 类型守卫

class Dog {
    bark() { console.log('Woof!'); }
}

class Cat {
    meow() { console.log('Meow!'); }
}

function makeSound(animal: Dog | Cat) {
    if (animal instanceof Dog) {
        animal.bark();  // animal 被推断为 Dog
    } else {
        animal.meow();  // animal 被推断为 Cat
    }
}

# in 类型守卫

interface Fish {
    swim: () => void;
}

interface Bird {
    fly: () => void;
}

function move(animal: Fish | Bird) {
    if ("swim" in animal) {
        animal.swim();  // animal 被推断为 Fish
    } else {
        animal.fly();   // animal 被推断为 Bird
    }
}

# 自定义类型守卫

interface Fish {
    swim: () => void;
}

interface Bird {
    fly: () => void;
}

function isFish(animal: Fish | Bird): animal is Fish {
    return (animal as Fish).swim !== undefined;
}

function move(animal: Fish | Bird) {
    if (isFish(animal)) {
        animal.swim();  // animal 被推断为 Fish
    } else {
        animal.fly();   // animal 被推断为 Bird
    }
}

# 十、工具类型

TypeScript 提供了多个内置工具类型:

# Partial(可选)

interface User {
    id: number;
    name: string;
    email: string;
}

// 所有属性变为可选
type PartialUser = Partial<User>;

const user: PartialUser = {
    name: 'Alice'
};

# Required(必需)

interface User {
    id?: number;
    name?: string;
}

// 所有属性变为必需
type RequiredUser = Required<User>;

const user: RequiredUser = {
    id: 1,
    name: 'Alice'
};

# Readonly(只读)

interface User {
    id: number;
    name: string;
}

// 所有属性变为只读
type ReadonlyUser = Readonly<User>;

const user: ReadonlyUser = {
    id: 1,
    name: 'Alice'
};

// user.name = 'Bob';  // 错误:只读

# Pick(选取)

interface User {
    id: number;
    name: string;
    email: string;
    age: number;
}

// 选取部分属性
type UserPreview = Pick<User, 'id' | 'name'>;

const preview: UserPreview = {
    id: 1,
    name: 'Alice'
};

# Omit(排除)

interface User {
    id: number;
    name: string;
    email: string;
    password: string;
}

// 排除部分属性
type PublicUser = Omit<User, 'password'>;

const user: PublicUser = {
    id: 1,
    name: 'Alice',
    email: 'alice@example.com'
};

# Record(记录)

type Role = 'admin' | 'user' | 'guest';

type Permissions = Record<Role, string[]>;

const permissions: Permissions = {
    admin: ['read', 'write', 'delete'],
    user: ['read', 'write'],
    guest: ['read']
};

# 十一、模块

# 导出

// math.ts
export const PI = 3.14159;

export function add(x: number, y: number): number {
    return x + y;
}

export class Calculator {
    multiply(x: number, y: number): number {
        return x * y;
    }
}

// 默认导出
export default class MathUtil {
    static square(x: number): number {
        return x * x;
    }
}

# 导入

// app.ts
import MathUtil, { PI, add, Calculator } from './math';

console.log(PI);
console.log(add(2, 3));

const calc = new Calculator();
console.log(calc.multiply(2, 3));

console.log(MathUtil.square(5));

// 重命名导入
import { add as sum } from './math';

// 导入所有
import * as math from './math';
console.log(math.PI);

# 十二、命名空间

namespace Validation {
    export interface StringValidator {
        isValid(s: string): boolean;
    }

    export class EmailValidator implements StringValidator {
        isValid(s: string): boolean {
            return /\S+@\S+\.\S+/.test(s);
        }
    }

    export class UrlValidator implements StringValidator {
        isValid(s: string): boolean {
            return /^https?:\/\//.test(s);
        }
    }
}

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

注意:在现代 TypeScript 项目中,推荐使用 ES6 模块而非命名空间。

# 十三、配置与编译

# tsconfig.json 常用选项

{
  "compilerOptions": {
    /* 基本选项 */
    "target": "ES2020",                // 编译目标版本
    "module": "commonjs",              // 模块系统
    "lib": ["ES2020", "DOM"],          // 包含的库
    "outDir": "./dist",                // 输出目录
    "rootDir": "./src",                // 源码目录
    
    /* 严格模式 */
    "strict": true,                    // 启用所有严格类型检查
    "noImplicitAny": true,             // 禁止隐式 any
    "strictNullChecks": true,          // 严格的 null 检查
    "strictFunctionTypes": true,       // 严格的函数类型检查
    "noUnusedLocals": true,            // 未使用的局部变量报错
    "noUnusedParameters": true,        // 未使用的参数报错
    
    /* 模块解析 */
    "moduleResolution": "node",        // 模块解析策略
    "baseUrl": "./",                   // 基础路径
    "paths": {                         // 路径映射
      "@/*": ["src/*"]
    },
    "esModuleInterop": true,           // ES 模块互操作
    
    /* 其他 */
    "skipLibCheck": true,              // 跳过库文件类型检查
    "forceConsistentCasingInFileNames": true,
    "declaration": true,               // 生成 .d.ts 声明文件
    "sourceMap": true,                 // 生成 source map
    "removeComments": true             // 移除注释
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

# 编译命令

# 编译单个文件
tsc hello.ts

# 编译项目(使用 tsconfig.json)
tsc

# 监听模式
tsc --watch

# 指定配置文件
tsc --project tsconfig.prod.json

# 十四、实用技巧

# 类型推断技巧

// 从函数返回值推断
function createUser() {
    return {
        id: 1,
        name: 'Alice',
        email: 'alice@example.com'
    };
}

type User = ReturnType<typeof createUser>;
// User 类型为 { id: number; name: string; email: string; }

# 常量断言

// 普通对象
const config = {
    host: 'localhost',
    port: 3000
};
// config 类型:{ host: string; port: number; }

// 使用 const 断言
const config = {
    host: 'localhost',
    port: 3000
} as const;
// config 类型:{ readonly host: "localhost"; readonly port: 3000; }

// 数组
const colors = ['red', 'green', 'blue'] as const;
// colors 类型:readonly ["red", "green", "blue"]

# 索引签名

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

const dict: Dictionary = {
    name: 'Alice',
    age: 30,
    city: 'Beijing'
};

# 映射类型

type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

interface User {
    id: number;
    name: string;
}

type ReadonlyUser = Readonly<User>;
// { readonly id: number; readonly name: string; }

# 十五、总结

TypeScript 通过静态类型系统为 JavaScript 添加了强大的类型安全保障:

  • 基础类型:基本类型、联合类型、字面量类型
  • 接口:对象类型、可选属性、只读属性、继承
  • 函数:类型注解、重载、泛型
  • 类:访问修饰符、继承、抽象类
  • 泛型:函数、类、接口、约束
  • 枚举:数字枚举、字符串枚举
  • 类型守卫:typeof、instanceof、in、自定义
  • 工具类型:Partial、Required、Pick、Omit、Record
  • 模块:导入导出、命名空间

掌握这些核心概念后,你可以编写类型安全、易于维护的 TypeScript 代码。更多高级特性(如条件类型、infer 关键字、装饰器等),详见 TypeScript高级特性详解。

祝你变得更强!

编辑 (opens new window)
#TypeScript#JavaScript
上次更新: 2025/11/07
JavaScript高级特性详解
TypeScript高级特性详解

← JavaScript高级特性详解 TypeScript高级特性详解→

最近更新
01
AI编程时代的一些心得
09-11
02
Claude Code与Codex的协同工作
09-01
03
Claude Code 最佳实践(个人版)
08-01
更多文章>
Theme by Vdoing | Copyright © 2018-2025 京ICP备2021021832号-2 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式