react4-TS、TS&React

TS

下载

  • TS:TypeScript:如何设置 TypeScript npm install -g typescript

  • Node.Js

  • ts-node:npm install -g ts-node typescript

    • 找到npm的全局安装目录:npm config get prefix

    • 将npm的安装路径添加到path的系统变量中

    • 重启CMD输入ts-node --versiontsc --version

  • vscode插件:

    • JavaScript and TypeScript Nightly

    • Code Runner(可直接运行ts代码)

企业微信截图_20250828144712

修改code runner的快捷键为:shift + enter


编译

  1. 在终端中输入:tsc -init 会生成tsconfig.json文件,接着可成功运行TS代码

  2. 输入:tsc .\xx.ts可生成对应的JS代码,但是这样生成JS代码是老版本(使用var、无箭头函数)

  3. 在tsconfig.json中配置:target: xxx版本JS

  4. 在终端 中输入:tsc 即可得到新版本的JS代码(编译所有)

  5. 通过include/exclude配置需要/不需要编译的文件

    TypeScript: TSConfig Reference - Docs on every TSConfig option

  6. 输入:npm init -y 可生成package.json文件


运行

type Person = {
    name: string
}

const person: Person = {
    name: 'yuanyu'
}

console.log(person.name)

wechat_2025-08-28_153820_043


语法

注解Annotations

  • 允许指定可以分配给定变量的值类型

  • 类型确定了就不能再更改

function multiple (x: number, y:number) :number{
    return x*y
}

类型推断:没有明确指定类型时,编译器会自动推断


数据类型

  • any类型:可表示任意类型、任意值,会禁用所有该变量及其属性的类型检查

  • void类型:表示任意值缺失的类型,常用于方法不返回值

  • never类型:表示函数无返回值或变量永远没有值 ,可在编译时捕获错误

    场景:

    • 总是抛出错误的方法

      function throwError(msg: string) :never {
          throw new Error(msg)
      }
      
    • 无限循环的方法

      function infiteLoop() :never{
          while(true){}
      }
      
    • 永远没有值的变量

      let x:never
      
      function neverReturn() :never{
          while(true){}
      }
      
      x=neverReturn()
      
  • Array数组类型:存储相同数据类型的多值对象

    const num: number[] = [1,2,3]
    const num: number[][] = [[1,2,3]]
    const num: number[][][] = [[[1,2,3]]]
    const num: Array<number> = [1,2,3]
    
  • Object对象类型:属性集合(键值对形式)

    const person: { name: string, age: number, address: string } = {
        name: 'yuanyu',
        age: 24,
        address: '江西省'
    }
    

交集类型&

集合了多个类型

type Person = {
    name: string,
    age: number
}

type Employee = {
    id: number,
    title: string
}

type PersonAndEmployee = Person & Employee

const alice: PersonAndEmployee = {
    name: 'sha',
    age: 12,
    id: 1,
    title: 'sdk'
}

联合类型|

可以包含一个或多个可能的类型

let myVar: number | string
const items: (number | string)[] = [1,2,'aaa']
type Person = {
    name: string,
    age: number
}

type Employee = {
    id: number,
    title: string
}

type PersonAndEmployee = Person | Employee

const alice: PersonAndEmployee = {
    name: 'sha',
    age: 12,
    id: 1
}

console.log(alice)

字面量类型Literal

字面量类型的变量只能有一个特定值

let color: 'red' | 'blue' | 'green'
color = 'red'
color = 'yellow' //不能将类型“"yellow"”分配给类型“"red" | "blue" | "green"”

元组类型tuple

元素可以有不同数据类型的数组,有序且序列长度已知

let myTuple: [string, number] = ['hello', 42]
let [first, second] = myTuple
console.log(first) //hello
console.log(second) //42

枚举类型Enums

定义一组常量类型的方法

enum Weather {
    sunny = 'Sunny',
    windy = 'Windy',
    rainy = 'Rainy'
}

let today : Weather
today = Weather.rainy
console.log(today) //Rainy

类型别名Alias

创建类型新名称

type User = {
    name: string,
    age: number,
    location: string
}

const printUserInfo = (user:User) => {
    return `Name: ${user.name} Age: ${user.age} Location: ${user.location}`
}

const res = printUserInfo({
    name: 'yuanyu',
    age: 24,
    location: 'China'
})

console.log(res)

可选属性

type User = {
    name: string,
    age: number,
    location?: string
}

修饰符

  • public:可在任何地方访问,无论内部还是外部

  • private:只能从类的内部访问

  • protected:可从内部和扩展子类访问

class Animal{
    public name: string
    private age: number
    protected species: string

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

    public getName() :string{
        return this.name
    }

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

    protected getSpecies() : string{
        return this.species
    }

    // 类内部可访问所有修饰符的属性(补充)
    public getAnimalDetails(): string {
        return `类内部访问: Name=${this.name}, Age=${this.age}, Species=${this.species}`;
    }
}

const dog = new Animal('GXH', 30, '恋爱脑')
console.log(dog) // Animal { name: 'GXH', age: 30, species: '恋爱脑' }
// console.log(dog.age) // 属性“age”为私有属性,只能在类“Animal”中访问

class Cat extends Animal{
    constructor(name:string, age: number, species: string){
        super(name, age, species)
    }

    // 子类中访问父类属性
    public getCatInfo(): string {
        let info = `子类访问: Name=${this.name}`
        info += `, Species=${this.species}`
        // info += `, Age=${this.age}` // 属性“age”为私有属性,只能在类“Animal”中访问
        // info += `, Age=${this.getAge()}` // 属性“getAge”为私有属性,只能在类“Animal”中访问
        return info;
    }
}

getter/setter

用于访问和修改类属性

class MyClass {
    private _myProperty: number = 0

    get myProperty() : number{
        return this._myProperty
    }

    set myProperty(value: number){ // 无返回值
        if (value > 0) this._myProperty = value 
    }
}

const myInstance = new MyClass()
console.log(myInstance.myProperty) // 0
myInstance.myProperty = 10
console.log(myInstance.myProperty) // 10

接口interface

一种定义对象/函数/类形状的方式,指定对象必须有的属性及其类型

interface Person {
    firstName: string
    lastName: string
    age: number
}

const person: Person = {
    firstName: 'abc',
    lastName: 'ddd',
    age: 20
}
interface MathOperation {
    (x: number, y: number): number
}

const add: MathOperation  = (a, b) => a + b
const multiply: MathOperation = (a, b) => a * b
interface Vehicle {
    start() : void
    stop(): void
}

class Car implements Vehicle{
    start() {
        console.log('start')
    }

    stop() {
        console.log('stop')
    }
}

interface和type的区别

  • 基本语法:

    // interface 语法
    interface User {
      name: string;
      age: number;
    }
    
    // type 语法
    type User = {
      name: string;
      age: number;
    };
    
  • 扩展方式:

    • interface:使用extends关键字扩展
    • type:使用&符号扩展
    interface Person {
      name: string;
    }
    
    interface Student extends Person {
      grade: number;
    }
    ------------------------
    type Person = {
      name: string;
    };
    
    type Student = Person & {
      grade: number;
    };
    
  • interface具有声明合并,如果同名会自动合并,type则会报错

  • type可以表示联合类型、交叉类型、基本类型等,而interface主要用于描述对象/函数/类的形状

  • interface可用原型为已有类型添加新属性‘

    interface String {
      padLeft(n: number): string;
    }
    
    String.prototype.padLeft = function(n: number) {
      // 实现...
    };
    

泛型

能够定义函数、类、接口,以便可以与不同类型的数据一起工作

可以创建针对不同类型数据的通用函数、类、接口

const printString = (x: string) => console.log(x)
const printNumber = (x: number) => console.log(x)
const printBoolean = (x: boolean) => console.log(x)


printString('hello')
printNumber(1)
printBoolean(true)

优化①:使用any类型

const myPrint = (x:any) => console.log(x)
myPrint('hello')
myPrint(1)
myPrint(true)

优化②:使用泛型

function myPrint<T>(x: T) {
    console.log(x)
}

myPrint('hello')
myPrint(1)
myPrint(true)

function uniqueDataFunc<Type>(
    item: Type,
    defaultValue: Type
): [Type, Type] {
    return [item, defaultValue]
}

const res1 = uniqueDataFunc<number>(10, 20)
const res2 = uniqueDataFunc<string>('a', 'b')
console.log(res1) // [ 10, 20 ]
console.log(res2) // [ 'a', 'b' ]
function uniqueDataFunc<T>(
    item: T,
    defaultValue: T
): [T, T] {
    return [item, defaultValue]
}

interface Dog {
    name: string
    breed: string
}

const dog = uniqueDataFunc<Dog>(
    {name: '1', breed:'abc'},
    {name: '2', breed:'abc'}
)

console.log(dog)
// 随机获取键值对
function getRandomValuePair<T>(obj: { [key: string]: T }): {
    key: string
    value: T
} {
    const keys = Object.keys(obj)
    const randomKey = keys[Math.floor(Math.random() * keys.length)]
    return {
        key: randomKey,
        value: obj[randomKey]
    }
}

const stringObject = { a: 'apple', b: 'banana', c: 'cherry' }
const randomStringPair = getRandomValuePair(stringObject)
console.log(randomStringPair)

const numberObject = { one: 1, two: 2, three: 3 }
const randomNumberPair = getRandomValuePair(numberObject)
console.log(randomNumberPair)
// 过滤数组
function filterArray<T>(array: T[], condition: (item: T) => boolean): T[] {
    return array.filter((item) => condition(item))
}

const numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const evenNumbers = filterArray<number>(numberArray, (num) => num % 2 === 0)
console.log(evenNumbers) // [ 2, 4, 6, 8, 10 ]

const stringArray = ['apple', 'banana', 'cherry', 'date']
const shortWords = filterArray<string>(stringArray, (word) => word.length < 6)
console.log(shortWords) // [ 'apple', 'date' ]

interface Fruit {
    name: string
    color: string
}

const fruitArray: Fruit[] = [
    { name: 'apple', color: 'red' },
    { name: 'banana', color: 'yellow' },
    { name: 'cherry', color: 'red' }
]
const redFruit = filterArray<Fruit>(fruitArray, (fruit) => fruit.color === 'red')
console.log(redFruit) // [ { name: 'apple', color: 'red' }, { name: 'cherry', color: 'red' } ]

对象的泛型:obj: { [key: string]: T }

函数表达式的泛型:condition: (item: T) => boolean


// 交换值
function reversePair<T, U>(value1: T, value2: U): [U, T] {
    return [value2, value1]
}

const reverse = reversePair(1, 2)
console.log(reverse) // [ 2, 1 ]

类型缩放

类型缩放是在一个条件代码块中精炼变量类型的过程

类型守卫

类型守卫是一种机制,帮助TS更精确理解和缩小类型

  • typeof操作符

    type MyType = string | number
    
    function exampleFunc(value: MyType): void {
        if (typeof value === 'string') console.log(value.toUpperCase())
        else console.log(value.toFixed(2))    
    }
    
    exampleFunc('hello') // HELLO
    exampleFunc(42) // 42.00
    
  • instanceof操作符

    class Dog {
        bark(): void {
            console.log("Woof!")
        }
    }
    class Cat {
        meow(): void {
            console.log("Meow!")
        }
    }
    
    function animalSound(animal: Dog | Cat): void{
        if (animal instanceof Dog) animal.bark()
        else animal.meow()
    }
    
    const myDog = new Dog()
    const myCat = new Cat()
    
    animalSound(myDog) // Woof!
    animalSound(myCat) // Meow!
    
  • 交集类型缩小类型:

    交集类型:允许将多个类型组合成一个单一类型,有每个单独类的所有属性

    type Employee = { 
        id: number
        name: string
    }
    
    type Manager = {
        department: string
        role: string
    }
    
    type ManagerWithEmployeeInfo = Employee & Manager
    
    const manager: ManagerWithEmployeeInfo = {
        id: 123,
        name: "John Doe",
        department: "Engineering",
        role: "Team Lead"
    }
    
    console.log(manager.id) // 123
    console.log(manager.name) // John Doe
    console.log(manager.department) // Engineering
    console.log(manager.role) // Team Lead
    

axios

import axios from 'axios'
import type { AxiosResponse } from 'axios'


interface Todo {
    userId: number
    id: number
    title: string
    completed: boolean
}
const fetchData = async () => {
    try {
        const res: AxiosResponse<Todo> = await axios.get('https://jsonplaceholder.typicode.com/todos/1')
        console.log(res.data)

    } catch (error: any) {
        if (axios.isAxiosError(error)) console.error(error.message)
        if (error.response) {
            console.log(error.response.status)
            console.log(error.response.data)

        } else {
            console.log(error.message)
        }
    }
}

fetchData() // { userId: 1, id: 1, title: 'delectus aut autem', completed: false }
// package.json
{
  "dependencies": {
    "axios": "^1.11.0"
  }
}
// tsconfig.json
{
    "compilerOptions": {
        "target": "ES5",
        "lib": [
            "ES2015",
            "DOM"
        ]
    }
}

Express

import express = require('express')
import { Request, Response } from 'express'

const app = express()
const port = 3000

app.get('/', (req: Request, res: Response) => {
    res.send('Hello TS with Express')
})

app.listen(port, () => {
    console.log('node server is running');
})

企业微信截图_20250901095219


TS & React

创建项目:npm i vite@latest

选择react、Typescript

企业微信截图_20250901100033

扩展是tsx后缀,创建的文件需要tsx后缀


传递参数

// type UserShape = {
//   name: string
//   age: number
//   isStudent: boolean
// }

interface UserShape {
  name: string
  age: number
  isStudent: boolean
}

// const User = ({name, age, isStudent}:UserShape) => {
// FC表示函数式组件(Functional Component)的类型
const User: FC<UserShape> = ({name, age, isStudent}) => {
  return (
    <div>
      <h2>name: {name} </h2>
      <h2>age: {age} </h2>
      <h2>isStudent: {isStudent ? 'Yes' : 'False'} </h2>
    </div>
  )
}

export default User
import User from './Components/User'

const App = () => {
  return (
    <div>
      <User name='yuanyu' age={24} isStudent={true} />
    </div>
  )
}

export default App

企业微信截图_20250901102141


带children

import User from './Components/User'

const App = () => {
  return (
    <div>
      <User>
        <h2>hello</h2>
      </User>
    </div>
  )
}

export default App
import type { ReactNode } from "react"

interface UserShape {
  children: ReactNode
}

const User = ({children}: UserShape) => {
  return (
    <div>
      {children}
    </div>
  )
}

export default User

带函数

import Button from "./Components/Button"

const App = () => {
  const handleClick = () => {
    console.log('click button')
  }

  return (
    <div>
      <Button label='This is a text paragraph' handleClick={handleClick} disable={false} />
    </div>
  )
}

export default App
import React, { type FC } from 'react'

type ButtonInfo = {
    label: string
    handleClick: () => void
    disable: boolean
}

const Button: FC<ButtonInfo> = ({label, handleClick, disable}) => {
  return (
    <button onClick={handleClick} disabled={disable}>
        <span>{label}</span>
    </button>
  )
}

export default Button

useState

import { useState } from 'react'

const Counter = () => {
    const [count, setCount] = useState<number>(0)

    return (
        <div>
            <h1>{count}</h1>
            <button onClick={() => setCount(count+1)}>+</button>
            <button onClick={() => setCount(count-1)}>-</button>
        </div>
    )
}

export default Counter
import { useRef, useState, type FormEvent } from 'react'

interface FormData {
    name: string
    email: string
    password: string
}

const Form = () => {
    const [submittedData, setSubmittedData] = useState<FormData>({
        name: '',
        email: '',
        password: ''
    })

    const name = useRef<HTMLInputElement>(null)
    const email = useRef<HTMLInputElement>(null)
    const password = useRef<HTMLInputElement>(null)

    const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
        e.preventDefault()
        const nameValue = name.current!.value
        const emailValue = email.current!.value
        const passwordValue = password.current!.value

        setSubmittedData({
            name: nameValue,
            email: emailValue,
            password: passwordValue
        })
    }

    return (
        <form onSubmit={handleSubmit}>
            <input type="text" placeholder='enter your name' ref={name}/>
            <input type="email" placeholder='enter your email' ref={email}/>
            <input type="password" placeholder='enter your password' ref={password}/>
            <button type='submit'>Submit</button>

            <section>
                <h2>Name:{submittedData.name}</h2>
                <h2>Email:{submittedData.email}</h2>
                <h2>Password:{submittedData.password}</h2>
            </section>
        </form>
    )
}

export default Form

事件

  • KeyboardEvent
  • FocusEvent
  • DragEvent
  • ClipboardEvent
  • TouchEvent
  • WheelEvent:处理鼠标滚轮操作
  • AnimationEvent
  • TransitionEvent
  • SyntheticEvent:所有 React 合成事件的基类,其他事件类型都继承自它

元素

  1. 表单相关元素
    • <HTMLTextAreaElement>:文本域元素(<textarea>
    • <HTMLSelectElement>:下拉选择框元素(<select>
    • <HTMLFormElement>:表单元素(<form>
    • <HTMLLabelElement>:标签元素(<label>
    • <HTMLFieldSetElement>:字段集元素(<fieldset>
  2. 媒体相关元素
    • <HTMLImageElement>:图片元素(<img>
    • <HTMLVideoElement>:视频元素(<video>
    • <HTMLAudioElement>:音频元素(<audio>
    • <HTMLMediaElement>:媒体元素的基类(包含视频和音频的共同属性)
  3. 容器与文本元素
    • <HTMLDivElement>:div 容器元素
    • <HTMLSpanElement>:span 文本容器元素
    • <HTMLParagraphElement>:段落元素(<p>
    • <HTMLHeadingElement>:标题元素(<h1><h6> 的统称)
    • <HTMLUListElement>:无序列表(<ul>
    • <HTMLOListElement>:有序列表(<ol>
    • <HTMLLIElement>:列表项(<li>
  4. 链接与框架元素
    • <HTMLAnchorElement>:链接元素(<a>
    • <HTMLIFrameElement>:iframe 框架元素
  5. 其他常用元素
    • <HTMLBodyElement>:body 元素
    • <HTMLTableElement>:表格元素(<table>
    • <HTMLInputElement>:输入框元素(包括 text、checkbox、radio 等类型)
    • <HTMLButtonElement>:按钮元素
    • <HTMLCanvasElement>:画布元素(<canvas>
    • <HTMLProgressElement>:进度条元素(<progress>
    • <HTMLMeterElement>:度量元素(<meter>

useContext

// MyContext.tsx
import { createContext, useState, type FC, type ReactNode } from "react"

interface MyContextProps {
    count: number
    increment: () => void
    decrement: () => void
}

export const MyContext = createContext<MyContextProps>({
    count: 0,
    increment: () => { },
    decrement: () => { }
})

interface MyProviderProps {
    children: ReactNode
}

export const MyProvider: FC<MyProviderProps> = ({ children }) => {
    const [count, setCount] = useState(0)
    const increment = () => setCount(count + 1)
    const decrement = () => setCount(count - 1)
    return <MyContext.Provider value={{ count, increment, decrement }}>
        {children}
    </MyContext.Provider>
}
// main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
import { MyProvider } from './MyContext.tsx'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <MyProvider>
      <App />
    </MyProvider>
  </StrictMode>,
)

使用:

import  {useContext} from 'react'
import { MyContext } from '../MyContext'

const Counter = () => {
    const {count, increment, decrement} = useContext(MyContext)
    return (
        <div>
            <p>{count}</p>
            <button onClick={increment}>+</button>
            <button onClick={decrement}>-</button>
        </div>
    )
}

export default Counter

useReducer

import React, { useReducer } from 'react'

type State = {count: number}
type Action = {type: 'INCREMENT'} | {type: 'DECREMENT'}

const reducer = (state: State, action: Action) => {
    switch (action.type) {
        case 'INCREMENT':
            return { count: state.count + 1 }
        case 'DECREMENT':
            return { count: state.count - 1 }
        default:
            return state
    }
}

const Counter = () => {
    const [state, dispatch] = useReducer(reducer, { count: 0 })
    return (
        <div>
            <p>{state.count}</p>
            <button onClick={() => dispatch({type:'INCREMENT'})}>+</button>
            <button onClick={() => dispatch({type:'DECREMENT'})}>-</button>
        </div>
    )
}

export default Counter
posted @ 2025-09-01 18:13  原语  阅读(12)  评论(0)    收藏  举报