《第七章》TS工程基础:检查指令与类型声明实战

目录

[1.TS 工程层面基础能力总结(含检查指令、类型声明、命名空间等)](#1.TS 工程层面基础能力总结(含检查指令、类型声明、命名空间等))

[1. 类型检查指令:控制单行/文件的类型检查范围](#1. 类型检查指令:控制单行/文件的类型检查范围)

关键案例(简化版)

[2. 类型声明:定义无逻辑的类型信息,生成.d.ts文件](#2. 类型声明:定义无逻辑的类型信息,生成.d.ts文件)

关键案例(简化版)

[3. 让类型定义全面覆盖项目:解决无类型、非代码文件等问题](#3. 让类型定义全面覆盖项目:解决无类型、非代码文件等问题)

[3.1 DefinitelyTyped:@types包提供第三方库类型](#3.1 DefinitelyTyped:@types包提供第三方库类型)

[3.2 扩展已有类型:补全全局变量/模块类型](#3.2 扩展已有类型:补全全局变量/模块类型)

[4. 三斜线指令:声明当前文件依赖的类型声明文件](#4. 三斜线指令:声明当前文件依赖的类型声明文件)

关键案例(简化版)

[5. 命名空间:组织强相关逻辑,实现简单模块化](#5. 命名空间:组织强相关逻辑,实现简单模块化)

关键案例(简化版)

[6. 仅类型导入:区分"值导入"与"类型导入"](#6. 仅类型导入:区分“值导入”与“类型导入”)

关键案例(简化版)

[7. 扩展阅读:JS文件中通过JSDoc获类型提示](#7. 扩展阅读:JS文件中通过JSDoc获类型提示)

关键案例(简化版)

1.TS 工程层面基础能力总结(含检查指令、类型声明、命名空间等)

1. 类型检查指令:控制单行/文件的类型检查范围

通过行内注释指令,灵活控制TypeScript对代码的检查范围,避免不必要的类型报错,核心包含4个指令:

|-----------------------|----------------------|---------------|
| 指令 | 作用 | 推荐度 |
| // @ts-ignore | 强制忽略下一行代码的所有类型检查 | 不推荐(易滥用) |
| // @ts-expect-error | 仅当下一行有类型错误时生效,无错误则报错 | 推荐(更严谨) |
| // @ts-check | 为JavaScript文件开启类型检查 | 按需使用 |
| // @ts-nocheck | 禁用当前文件(TS/JS)的所有类型检查 | 按需使用(如JS迁移初期) |

关键案例(简化版)
复制代码
// @ts-ignore:即使下一行无错也不报错(不推荐)
const name1: string = 599; 

// @ts-expect-error:下一行有错误,正常生效(推荐)
const name2: string = 599; 

// @ts-expect-error:下一行无错误,会触发"无意义指令"报错
const age: number = 18; 

// @ts-check:JS文件开启类型检查
/** @type {string} */ // JSDoc标注类型
const username = 599; // 报错:类型不匹配(number不能赋值给string)

let userAge = 18;
userAge = "20"; // 报错:类型不匹配(string不能赋值给number)

2. 类型声明:定义无逻辑的类型信息,生成.d.ts文件

通过declare语法定义仅包含类型的信息(无实际代码逻辑),编译后生成.d.ts类型声明文件,供其他文件或项目获取类型提示,核心用于:声明变量、接口、函数、类的类型。

关键案例(简化版)
复制代码
// 声明变量类型
declare let message: string;
// 声明接口类型
declare interface User {
  id: number;
  name: string;
}
// 声明函数类型
declare function getUser(id: number): User;

// 使用声明的类型(无需实现逻辑,仅用类型)
const user: User = getUser(1);
console.log(user.name);

// 源代码 index.ts
const getUserName = (user: User): string => user.name;
interface User { id: number; name: string; }

// 编译后生成的 index.d.ts(仅保留类型)
declare const getUserName: (user: User) => string;
declare interface User {
    id: number;
    name: string;
}

3. 让类型定义全面覆盖项目:解决无类型、非代码文件等问题

针对项目中"无类型npm包""非代码文件导入""全局变量"三类无类型场景,通过类型声明补全类型,确保项目类型全覆盖。

3.1 DefinitelyTyped:@types包提供第三方库类型

@types/xxx是TypeScript官方维护的类型库(如@types/react@types/lodash),为无内置类型的JS库提供类型支持,安装后TS会自动加载。

案例 :使用无类型库lodash时,安装@types/lodash即可获类型提示

复制代码
# 安装lodash及其类型声明
npm install lodash @types/lodash --save

import { debounce } from 'lodash';
// 自动获得debounce函数的类型提示(参数、返回值类型)
const delayFn = debounce(() => console.log('延迟执行'), 1000);
3.2 扩展已有类型:补全全局变量/模块类型

通过"接口合并""declare module"扩展已有类型,如补全window全局变量、扩展模块类型。

复制代码
// 扩展内置Window接口,添加全局变量userTracker
interface Window {
  userTracker: (event: string) => void;
}

// 使用扩展后的全局变量(无类型报错)
window.userTracker('button_click');

// 声明.d.ts文件:为所有.md文件定义类型
declare module '*.md' {
  const content: string; // .md文件导入后是字符串
  export default content;
}

// 实际使用:导入.md文件(无类型报错)
import note from './guide.md';
console.log(note); // 输出.md文件的文本内容

// 为无类型包"simple-utils"声明类型
declare module 'simple-utils' {
  // 声明包内的函数类型
  export const formatDate: (date: Date) => string;
  export const getRandom: (min: number, max: number) => number;
}

// 使用无类型包(获类型提示)
import { formatDate } from 'simple-utils';
console.log(formatDate(new Date())); // 无报错,有类型提示

4. 三斜线指令:声明当前文件依赖的类型声明文件

作用类似"声明文件的导入语句",指定当前文件依赖的外部类型声明(项目内文件、@types包、TS内置声明),需放在文件顶部。

|--------------------------------|-----------------------------|-----------------|
| 指令格式 | 作用 | 适用场景 |
| /// <reference path="路径" /> | 依赖项目内的其他.d.ts文件 | 项目内自定义声明文件依赖 |
| /// <reference types="包名" /> | 依赖@types下的类型包(如@types/node) | 使用第三方库的类型声明 |
| /// <reference lib="库名" /> | 依赖TS内置类型库(如dom、es2020) | 使用浏览器/ES内置API类型 |

关键案例(简化版)
复制代码
// 依赖同目录下的user.d.ts文件
/// <reference path="./user.d.ts" />

// 使用user.d.ts中声明的User类型
const user: User = { id: 1, name: '张三' };

// 依赖@types/node(使用Node.js的fs模块类型)
/// <reference types="node" />

import fs from 'fs';
// 获fs.readFileSync的类型提示
const content = fs.readFileSync('./file.txt', 'utf-8');

// 依赖TS内置的dom类型(使用document、window等浏览器API)
/// <reference lib="dom" />

// 无类型报错(获document的类型提示)
const button = document.getElementById('submit');

5. 命名空间:组织强相关逻辑,实现简单模块化

用于将一组强相关的类、函数、类型组织到一个"命名空间"下,避免全局变量污染,支持嵌套和合并,编译后类似IIFE(立即执行函数)。

关键案例(简化版)
复制代码
// 声明命名空间:区分现实货币和虚拟货币支付逻辑
export namespace RealCurrencyPay {
  export class WeChatPay {
    pay(amount: number) {
      console.log(`微信支付:${amount}元`);
    }
  }
  export class AliPay {
    pay(amount: number) {
      console.log(`支付宝支付:${amount}元`);
    }
  }
}

export namespace VirtualCurrencyPay {
  export class QQCoinPay {
    pay(amount: number) {
      console.log(`QQ币支付:${amount}币`);
    }
  }
}

// 使用命名空间中的类
const weChatPay = new RealCurrencyPay.WeChatPay();
weChatPay.pay(100); // 输出:微信支付:100元

const qqCoinPay = new VirtualCurrencyPay.QQCoinPay();
qqCoinPay.pay(50); // 输出:QQ币支付:50币

// 声明命名空间:为UI库声明类型
declare namespace UILib {
  export interface ButtonProps {
    text: string;
    onClick: () => void;
  }
  export function Button(props: ButtonProps): void;
}

// 使用命名空间中的类型
const btnProps: UILib.ButtonProps = {
  text: '点击',
  onClick: () => alert('点击了')
};
UILib.Button(btnProps);

6. 仅类型导入:区分"值导入"与"类型导入"

通过import type语法明确区分"导入的值"和"导入的类型",提升代码可读性,避免类型与值混淆,TS编译后会移除类型导入代码。

关键案例(简化版)
复制代码
// 源文件 user.ts
export type User = { id: number; name: string };
export const getDefaultUser = (): User => ({ id: 0, name: '默认用户' });

// 导入文件 index.ts
import { getDefaultUser } from './user'; // 导入值(函数)
import type { User } from './user'; // 仅导入类型

const user: User = getDefaultUser(); // 正确使用类型和值

// TS 4.6+支持:同一导入语句中区分值和类型
import { getDefaultUser, type User } from './user';

const user: User = getDefaultUser();

// 1. React核心
import { useState, useEffect } from 'react';

// 2. UI组件(第三方→项目内)
import { Button } from 'antd';
import { CustomInput } from './CustomInput';

// 3. 工具函数(第三方→项目内)
import { debounce } from 'lodash';
import { formatTime } from './utils';

// 4. 仅类型导入
import type { User, Order } from './types';
import type { ButtonProps } from 'antd';

// 5. 样式文件
import styles from './index.module.scss';

7. 扩展阅读:JS文件中通过JSDoc获类型提示

在JS文件中,通过/** @type {import("库名").类型名} */语法,无需TS也能获得类型提示,适合JS项目逐步迁移TS的场景。

关键案例(简化版)
复制代码
// webpack.config.js(JS文件)
/** 
 * @type {import("webpack").Configuration} 
 * 导入webpack的Configuration类型,获完整配置提示
 */
const webpackConfig = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: './dist'
  },
  module: {
    rules: [
      { test: /\.js$/, use: 'babel-loader' } // 获rules的类型提示
    ]
  }
};

module.exports = webpackConfig;
相关推荐
关于不上作者榜就原神启动那件事1 小时前
心跳机制详解
java·前端·servlet
杀死那个蝈坦1 小时前
Redis 持久化 主从 哨兵 分片集群
前端·bootstrap·html
eason_fan1 小时前
什么是模块联邦?(Module Federation)
前端·javascript·前端工程化
VX:Fegn08951 小时前
计算机毕设|基springboot+Vue的校园打印系统设计与实现
java·前端·javascript·vue.js·spring boot·后端·课程设计
W.Y.B.G1 小时前
vue3项目中集成天地图使用示例
android·前端
m***11901 小时前
【前端】Node.js使用教程
前端·node.js·vim
QianhangQianping1 小时前
前端技术迭代深析:从 CSS 布局到状态管理的进化之路
前端·css