从零到一:基于STM32F030的SPI驱动74HC595实战解析
2026/5/11 18:27:22
主要学习react中ts的使用和概念
TypeScript 的核心思想是:给变量穿上约束的衣服。
letname:string="Gemini";letage:number=25;letisAI:boolean=true;// 数组的两种写法letskills:string[]=['React','TS'];letscores:Array<number>=[90,85];// 元组 (Tuple):固定长度和类型的数组letuser:[number,string]=[1,'Admin'];//普通函数定义functionadd(x:number,y:number):number{returnx+y;}letmyAdd=function(x:number,y:number):number{returnx+y;};// 定义函数类型typeGreetFn=(name:string)=>string;constsayHello:GreetFn=(n)=>`Hello,${n}`;Interface: 侧重于描述对象的结构,支持继承(extends)和声明合并。
Type: 更灵活,可以定义基本类型、联合类型、元组等。
interfaceLabelledValue{label:string;num?:number;}这是最常用的功能,用于定义对象的结构。
| 特性 | Interface | Type |
|---|---|---|
| 核心用途 | 定义对象的形状 | 定义任何类型(联合、元组等) |
| 扩展方式 | 使用extends关键字 | 使用&(交叉类型) |
| 重复定义 | 会自动合并(Declaration Merging) | 不允许重复定义 |
建议:定义公共 API 或组件 Props 时优先使用
interface;定义复杂逻辑、联合类型时使用type。
// 联合类型:变量可以是多种类型之一letstatus:"loading"|"success"|"error";letcurrentStatus:Status="loading";// 只能是这三个字符串之一// 类型守卫 (Type Guard)functionprintId(id:number|string){if(typeofid==="string"){console.log(id.toUpperCase());// 此时 TS 知道 id 是 string}else{console.log(id.toFixed());// 此时 TS 知道 id 是 number}}泛型是 TS 最强大的地方,它允许你在定义时不指定具体类型,而在使用时动态决定。
// 这里的 T 就像是一个变量占位符functionidentity<T>(arg:T):T{returnarg;}constres1=identity<string>("hello");// T 被确定为 stringconstres2=identity<number>(100);// T 被确定为 number在 TS 中,类型是有层级的。理解这一点能帮你解决 90% 的类型兼容性问题。
Top Types (顶级类型):any和unknown。
any: 彻底放弃检查,是代码中的“黑洞”。
unknown: 虽也是万能类型,但在使用前必须进行类型检查(类型收窄)。
Bottom Type (底层类型):never。表示永远不会出现的值。常用于穷举检查。
在 React 项目中,两者的界限日益模糊,但底层逻辑不同:
|)、交叉(&)、位运算等。Type 不能被重新打开添加属性。tsconfig.json决定了你的代码如何被“审判”。以下是生产环境中最关键的三个配置:
| 配置项 | 作用 | 为什么重要 |
|---|---|---|
strict: true | 开启所有严格模式 | 防止null导致的运行时崩溃,禁用隐式any。 |
noImplicitAny | 禁止隐式 any | 强制你思考每个变量的来源,是项目质量的底线。 |
paths | 路径别名 | 将../../../../components简化为@/components,解耦目录结构。 |
在定义组件 Props 时,利用 TS 的特性可以极大提升开发体验。
interface GreetProps { name: string; // 1. 可选属性 priority?: number; // 2. 字面量联合类型:限制范围 theme: 'dark' | 'light'; // 3. 复杂对象:引用其他接口 metadata: Record<string, unknown>; } // 推荐写法:使用普通函数解构 Props export const Greet = ({ name, theme = 'light' }: GreetProps) => { return <div className={theme}>Hello {name}</div>; };Hooks 是 React 的核心,其类型标注主要依靠泛型。
// 显式指定联合类型,处理“空状态” const [user, setUser] = useState<User | null>(null);const inputRef = useRef<HTMLInputElement>(null);(注意初始化为null)。const timerRef = useRef<number>();。不要直接使用any处理事件。React 提供了一整套事件类型,命名规则通常是React.[事件名]Event<HTML元素类型>。
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { console.log(e.target.value); // 这里 e.target 会被精准推断为 HTMLInputElement };TS 内置的工具类型其实就是类型函数。
Partial<T>: 把所有 Props 变可选。Omit<T, 'id'>: 复制 T 的所有属性,但剔除id。Pick<T, 'title' | 'desc'>: 只从 T 中挑选部分属性。当你需要组件支持多种类型的数据流时(如自定义下拉框、表格):
interface SelectProps<T> { options: T[]; onSelect: (value: T) => void; } // 在函数名前使用 <T,> 开启泛型 export const Select = <T,>({ options, onSelect }: SelectProps<T>) => { return ( <ul> {options.map((opt, i) => ( <li key={i} onClick={() => onSelect(opt)}>选择</li> ))} </ul> ); }; // 使用时,TS 会根据传入的 options 自动推断 T <Select options={[1, 2, 3]} onSelect={(val) => console.log(val + 1)} />