文章目录
- react 中 ts 常见应用
- 技术名词解释(React.FC)
- react中ts 应用总结
- 类型定义与安全保障
- 函数类型规范
- 组件类型定义与复用
- 项目维护与协作优势
- 与 React 生态整合
- vue3 中 ts 常见应用
- 技术名词解释(vue Ref)
- vue3中ts应用总结
react 中 ts 常见应用
- 类型定义基础
- 基本数据类型
- 在TypeScript中,基本数据类型包括
number
、string
、boolean
、null
、undefined
。例如,在React组件中定义一个状态变量来存储用户的年龄(number
类型):
这里import React, { useState } from 'react'; const MyComponent: React.FC = () => {const [userAge, setUserAge] = useState<number>(0);return (<div><p>User Age: {userAge}</p><button onClick={() => setUserAge(userAge + 1)}>Increment Age</button></div>); };
useState<number>
明确指定了状态userAge
的类型是number
。
- 在TypeScript中,基本数据类型包括
- 接口(interface)定义对象类型
- 接口用于定义对象的形状,描述对象应该具有哪些属性和方法。例如,定义一个表示用户信息的接口:
然后在React组件中使用这个接口类型来定义属性或状态:interface User {name: string;age: number;email: string; }
import React, { useState } from 'react'; const UserProfile: React.FC<{ user: User }> = ({ user }) => {return (<div><h2>{user.name}</h2><p>Age: {user.age}</p><p>Email: {user.email}</p></div>); };
- 接口用于定义对象的形状,描述对象应该具有哪些属性和方法。例如,定义一个表示用户信息的接口:
- 类型别名(type)
- 类型别名可以给一个类型起一个新的名字。例如,定义一个联合类型来表示用户角色:
然后可以在接口中使用这个类型别名来定义用户角色属性:type UserRole = 'admin' | 'user' | 'guest';
interface User {name: string;age: number;role: UserRole;email: string; }
- 类型别名可以给一个类型起一个新的名字。例如,定义一个联合类型来表示用户角色:
- 基本数据类型
- 函数类型定义
- 函数参数和返回值类型
- 在TypeScript中,需要明确函数的参数类型和返回值类型。例如,定义一个函数来计算两个数字的和:
const addNumbers = (num1: number, num2: number): number => {return num1 + num2; };
- 在React组件中,函数作为事件处理程序也需要定义类型。例如,定义一个按钮点击事件处理函数:
import React from 'react'; const MyComponent: React.FC = () => {const handleClick = (): void => {console.log('Button clicked');};return (<div><button onClick={handleClick}>Click Me</button></div>); };
- 在TypeScript中,需要明确函数的参数类型和返回值类型。例如,定义一个函数来计算两个数字的和:
- 函数类型别名
- 可以使用类型别名来定义函数类型。例如,定义一个类型别名来表示一个接受两个数字参数并返回一个数字的函数类型:
type MathFunction = (num1: number, num2: number) => number; const multiply: MathFunction = (num1, num2) => num1 * num2;
- 可以使用类型别名来定义函数类型。例如,定义一个类型别名来表示一个接受两个数字参数并返回一个数字的函数类型:
- 函数参数和返回值类型
- 组件类型定义
- 函数组件类型(React.FC)
- 在React中,函数组件可以使用
React.FC
(Function Component的缩写)来定义类型。它默认包含了children
属性的类型定义。例如:import React from 'react'; const MyComponent: React.FC<{ title: string }> = ({ title, children }) => {return (<div><h1>{title}</h1>{children}</div>); };
- 当组件接收一个事件处理函数作为属性时,也需要在组件类型定义中指定函数类型。例如,一个按钮组件接收一个
onClick
事件处理函数:import React from 'react'; type ButtonProps = {onClick: () => void;text: string; }; const MyButton: React.FC<ButtonProps> = ({ onClick, text }) => {return (<button onClick={onClick}>{text}</button>); };
- 在React中,函数组件可以使用
- 类组件类型定义
- 对于类组件,需要定义组件的
props
类型和state
类型。例如:import React, { Component } from 'react'; interface MyComponentProps {name: string; } interface MyComponentState {count: number; } class MyComponent extends Component <MyComponentProps, MyComponentState> {constructor(props: MyComponentProps) {super(props);this.state = { count: 0 };}render() {return (<div><p>Name: {this.props.name}</p><p>Count: {this.state.count}</p></div>);} }
- 对于类组件,需要定义组件的
- 函数组件类型(React.FC)
- 泛型(Generics)应用
- 在组件中使用泛型
- 泛型可以使组件更加通用。例如,定义一个泛型组件来渲染一个列表,这个列表可以是任何类型的数据:
import React from 'react'; interface ListItem<T> {data: T;key: string; } interface GenericListProps<T> {list: ListItem<T>[]; } const GenericList: React.FC<GenericListProps<any>> = ({ list }) => {return (<ul>{list.map((item) => (<li key={item.key}>{JSON.stringify(item.data)}</li>))}</ul>); };
- 当使用这个泛型组件时,可以指定具体的数据类型。例如,渲染一个用户列表:
import React from 'react'; interface User {name: string;age: number; } const users: User[] = [{ name: 'Alice', age: 25 },{ name: 'Bob', age: 30 } ]; const userListItems = users.map((user) => ({data: user,key: user.name })); const App: React.FC = () => {return (<div><h1>User List</h1><GenericList list={userListItems} /></div>); };
- 泛型可以使组件更加通用。例如,定义一个泛型组件来渲染一个列表,这个列表可以是任何类型的数据:
- 泛型函数在React中的应用
- 可以定义泛型函数来处理数据,然后在React组件中使用这些函数。例如,定义一个泛型函数来过滤数组中的元素:
在React组件中使用这个函数来过滤用户列表:const filterArray = <T>(array: T[], predicate: (item: T) => boolean): T[] => {return array.filter(predicate); };
import React, { useState } from 'react'; interface User {name: string;age: number; } const users: User[] = [{ name: 'Alice', age: 25 },{ name: 'Bob', age: 30 },{ name: 'Charlie', age: 35 } ]; const MyComponent: React.FC = () => {const [filteredUsers, setFilteredUsers] = useState<User[]>(users);const handleFilter = () => {const filtered = filterArray<User>(users, (user) => user.age > 25);setFilteredUsers(filtered);};return (<div><button onClick={handleFilter}>Filter Users</button><ul>{filteredUsers.map((user) => (<li key={user.name}>{user.name} - {user.age}</li>))}</ul></div>); };
- 可以定义泛型函数来处理数据,然后在React组件中使用这些函数。例如,定义一个泛型函数来过滤数组中的元素:
- 在组件中使用泛型
技术名词解释(React.FC)
-
定义与来源
React.FC
是TypeScript中用于定义函数式React组件的类型。它是FunctionComponent
的缩写,是从react
库中引入的一个类型定义。它实际上是一个泛型类型,用于描述组件的属性(props
)类型。例如:import React from 'react'; const MyComponent: React.FC<{ message: string }> = ({ message }) => {return <div>{message}</div>; };
- 在这里,
React.FC<{ message: string }>
表示MyComponent
是一个函数式组件,它接收一个具有message
属性(类型为string
)的props
对象。
-
默认包含的属性类型
React.FC
类型默认包含了children
属性的类型定义。这意味着如果你的组件需要接收子组件作为内容,React.FC
已经考虑到了这一点。例如:import React from 'react'; const ParentComponent: React.FC = ({ children }) => {return <div>{children}</div>; };
- 在这个例子中,
ParentComponent
可以像这样使用:<ParentComponent><p>Child content</p> </ParentComponent>
React.FC
类型中的children
属性类型是ReactNode
,ReactNode
是一个复杂的类型,它可以是React元素、字符串、数字、数组(包含React元素)等多种类型,这样就能够灵活地处理子组件的各种可能情况。
- 在这个例子中,
-
与普通函数类型的区别
- 类型检查的完整性
- 当使用
React.FC
时,TypeScript会对组件的属性进行更完整的类型检查。相比之下,简单地将组件定义为一个函数类型(如({ prop }: { prop: string }) => JSX.Element
),React.FC
提供了一些额外的类型推断和约束。例如,它能够更好地处理props
的可选属性和默认属性。
- 当使用
- 与React生态的集成性
React.FC
是专门为React函数式组件设计的类型定义,在与React的其他功能(如React.memo
、React.lazy
等)结合使用时,能够更好地遵循React的类型规范和最佳实践。例如,当使用React.memo
来优化组件性能时,React.FC
类型的组件能够更方便地进行属性比较,以决定是否需要重新渲染。
- 类型检查的完整性
-
在实际项目中的优势
- 代码可读性和可维护性
- 在大型React + TypeScript项目中,使用
React.FC
可以使组件的类型定义更加清晰。开发人员可以一眼看出组件接收哪些属性,并且这些属性的类型是什么。这有助于新开发人员快速理解组件的接口,提高代码的可读性和可维护性。
- 在大型React + TypeScript项目中,使用
- 类型安全
- 它提供了强大的类型安全保障,减少了因为属性类型错误而导致的运行时错误。例如,如果一个组件期望接收一个
number
类型的属性,但实际传入了一个string
类型的属性,TypeScript会在编译阶段就发出错误提示,而不是在运行时出现难以调试的问题。
- 它提供了强大的类型安全保障,减少了因为属性类型错误而导致的运行时错误。例如,如果一个组件期望接收一个
- 代码可读性和可维护性
react中ts 应用总结
TypeScript(TS)在 React 项目中的应用为项目开发带来诸多优势,涵盖类型安全、代码可读性与可维护性等关键层面,以下是具体总结:
类型定义与安全保障
- 基本数据类型:明确指定 React 组件内变量与属性的数据类型,像是
number
、string
、boolean
等。例如定义组件状态const [count, setCount] = useState<number>(0);
,保障状态值始终为数字,避免因类型不匹配引发的错误。 - 接口(interface):用于精准描述复杂对象结构。在处理用户信息、产品详情这类数据时,
interface
能清晰定义对象应含属性与类型,如interface User {id: number; name: string; email: string;}
,后续组件接收User
类型数据,不符结构便报错。 - 类型别名(type):为类型赋予新名称,方便复用与统一管理。定义联合类型
type Status = 'active' | 'inactive' | 'pending';
,用于表示业务状态,使代码逻辑更紧凑,维护成本降低。
函数类型规范
- 参数与返回值类型:给函数的输入输出明确定型。例如
const add = (a: number, b: number): number => a + b;
,传入非数字参数即刻报错;事件处理函数也不例外,const handleClick = (): void => console.log('Clicked');
保证执行逻辑正确。 - 函数类型别名:用
type
为函数类型起名,type Callback = (data: any) => void;
,方便统一管理同类型函数,增强代码可读性与规范性。
组件类型定义与复用
- 函数组件(React.FC):专用于函数式组件类型定义,自带
children
属性类型,如const MyComponent: React.FC<{ title: string }> = ({ title, children }) => (<div>{title}{children}</div>);
,既规范组件属性,又适配子组件嵌套场景。 - 类组件:结合
interface
定义props
与state
类型,interface Props { name: string; } interface State { count: number; } class MyClassComponent extends Component<Props, State>
,保障类组件在数据交互时的类型安全。 - 泛型组件:利用泛型
<T>
让组件适配不同数据类型,interface ListItem<T> { data: T; key: string; } const GenericList: React.FC<GenericListProps<T>>
,渲染用户、商品等各种列表游刃有余,提升组件复用性。
项目维护与协作优势
- 代码可读性:TS 的类型标注如同详尽注释,新成员能迅速掌握代码结构与数据流向,降低理解成本,加速开发迭代。
- 错误排查:在编译阶段揪出多数类型错误,避免上线后因数据类型问题引发运行时故障,大幅缩减调试时间与成本。
- 团队协作:统一的类型规范利于团队成员遵循相同标准,减少代码合并冲突,提升协作效率与项目质量。
与 React 生态整合
TS 与 React Router、Redux 等常用库适配良好。以 Redux 为例,搭配@reduxjs/toolkit
与 TS,精确定义state
、action
、reducer
类型,保障状态管理流程的严谨与稳定;React Router 中,为路由参数、链接属性规范类型,优化路由导航体验。
TypeScript 已然成为 React 项目不可或缺的利器,虽学习曲线稍陡,但长远看,投入产出比可观,助开发者打造高质量、易维护的 React 应用。
vue3 中 ts 常见应用
- 组件基础类型定义
defineComponent
函数:在Vue3中,通常使用defineComponent
函数来定义组件。这个函数可以帮助我们更好地结合TypeScript进行类型定义。例如,定义一个简单的HelloWorld组件:import { defineComponent } from 'vue'; export default defineComponent({setup() {return {message: 'Hello, World!'};},template: '<div>{{ message }}</div>' });
Props
类型定义:当组件需要接收属性(Props
)时,需要定义Props
的类型。可以使用interface
或者type
来定义。例如,定义一个接收name
属性的组件:import { defineComponent } from 'vue'; interface Props {name: string; } export default defineComponent({props: {name: String},setup(props: Props) {return {greeting: `Hello, ${props.name}!`};},template: '<div>{{ greeting }}</div>' });
- 这里
props
对象在setup
函数中被明确指定为Props
类型,确保了传入属性的类型正确。
- 这里
Ref
和Reactive
类型定义:在Vue3中,ref
和reactive
是用于创建响应式数据的函数。当使用它们时,也需要正确定义类型。- 对于
ref
,如果它包裹的数据是基本类型(如number
、string
等),类型推断通常可以正常工作。但如果需要明确类型,可以这样做:import { defineComponent, ref } from 'vue'; export default defineComponent({setup() {const count: Ref<number> = ref(0);return {count};},template: '<div>{{ count }}</div>' });
- 对于
reactive
,它通常用于创建复杂的响应式对象。例如:import { defineComponent, reactive } from 'vue'; interface State {user: {name: string;age: number;}; } export default defineComponent({setup() {const state: State = reactive({user: {name: 'John',age: 30}});return {state};},template: '<div>{{ state.user.name }} - {{ state.user.age }}</div>' });
- 对于
- 事件处理类型定义
- 当组件触发事件或者接收外部事件时,需要定义事件处理函数的类型。例如,定义一个按钮组件,它有一个
click
事件:import { defineComponent } from 'vue'; interface ButtonProps {text: string; } interface ButtonEmits {click: () => void; } export default defineComponent({props: {text: String},emits: {click: null},setup(props: ButtonProps, { emit }) {const handleClick = () => {emit('click');};return {handleClick,props};},template: '<button @click="handleClick">{{ props.text }}</button>' });
- 这里定义了
ButtonProps
用于组件接收的属性类型,ButtonEmits
用于定义组件向外发射的事件类型。在setup
函数中,事件发射函数emit
的调用符合ButtonEmits
中定义的类型。
- 这里定义了
- 当组件触发事件或者接收外部事件时,需要定义事件处理函数的类型。例如,定义一个按钮组件,它有一个
- 计算属性类型定义
- 计算属性在Vue3中也可以结合TypeScript进行类型定义。例如,有一个根据用户年龄判断是否成年的计算属性:
import { defineComponent, reactive } from 'vue'; interface State {user: {age: number;}; } export default defineComponent({setup() {const state: State = reactive({user: {age: 18}});const isAdult = computed(() => state.user.age >= 18);return {isAdult};},template: '<div>{{ isAdult }}</div>' });
- 计算属性
isAdult
的类型会根据计算逻辑自动推断为boolean
类型。如果计算逻辑比较复杂,可能需要手动调整类型或者添加类型注释来确保类型的准确性。
- 计算属性
- 计算属性在Vue3中也可以结合TypeScript进行类型定义。例如,有一个根据用户年龄判断是否成年的计算属性:
- 组件组合与插槽类型定义
- 组件组合:在Vue3中,组件可以通过组合的方式构建更复杂的UI。当组合组件时,需要确保组件之间传递的数据和事件的类型正确。例如,有一个包含标题组件和内容组件的布局组件:
import { defineComponent } from 'vue'; import TitleComponent from './TitleComponent.vue'; import ContentComponent from './ContentComponent.vue'; export default defineComponent({components: {TitleComponent,ContentComponent},setup() {return {};},template: '<div><TitleComponent/><ContentComponent/></div>' });
- 在实际应用中,需要根据
TitleComponent
和ContentComponent
的Props
和Emits
类型来确保它们在组合时的正确性。
- 在实际应用中,需要根据
- 插槽类型定义:插槽是Vue组件的一个重要特性。当定义带有插槽的组件时,也可以定义插槽内容的类型。例如,定义一个带有默认插槽的容器组件:
import { defineComponent } from 'vue'; interface ContainerProps {title: string; } export default defineComponent({props: {title: String},setup(props: ContainerProps) {return {props};},template: '<div><h1>{{ props.title }}</h1><slot/></div>' });
- 这里虽然没有对插槽内容进行详细的类型定义,但可以通过
v-slot
指令的语法和相关组件的使用场景来进一步约束插槽内容的类型。例如,如果这个容器组件主要用于包裹文本内容,那么可以期望插槽内容是字符串或者包含字符串的HTML元素。
- 这里虽然没有对插槽内容进行详细的类型定义,但可以通过
- 组件组合:在Vue3中,组件可以通过组合的方式构建更复杂的UI。当组合组件时,需要确保组件之间传递的数据和事件的类型正确。例如,有一个包含标题组件和内容组件的布局组件:
技术名词解释(vue Ref)
-
Ref
类型的定义与来源- 在Vue 3的TypeScript应用中,
Ref
是一个泛型接口类型,它来自于vue
库。具体来说,Ref
类型用于表示通过ref
函数创建的响应式引用的类型。当你使用ref
包裹一个值(如ref(0)
)时,这个返回值的类型就是Ref
类型。
- 在Vue 3的TypeScript应用中,
-
Ref
类型的作用- 类型安全保障
Ref
类型提供了类型安全的保障。以const count: Ref<number> = ref(0);
为例,Ref<number>
明确表示count
这个响应式引用内部存储的值是number
类型。这意味着在后续的代码中,当你访问或修改count.value
(ref
创建的响应式引用的值需要通过.value
来访问)时,TypeScript会检查操作是否符合number
类型的规则。例如,如果你试图将一个字符串赋值给count.value
,TypeScript会报错,防止类型不匹配的错误发生。
- 清晰的代码意图表达
- 它也能够清晰地表达代码的意图。通过显式地指定
Ref
类型,其他开发人员(包括你自己在后续维护代码时)可以很容易地理解这个变量是一个响应式引用,并且知道它内部存储的数据类型是什么。这有助于提高代码的可读性和可维护性。
- 它也能够清晰地表达代码的意图。通过显式地指定
- 类型安全保障
-
Ref
类型的泛型特性Ref
是一个泛型类型,这意味着它可以根据不同的类型参数来适应各种数据类型。除了number
类型,还可以用于string
、boolean
、object
等各种类型。例如:const message: Ref<string> = ref('Hello');
用于表示一个存储string
类型值的响应式引用。const flag: Ref<boolean> = ref(false);
用于表示一个存储boolean
类型值的响应式引用。- 对于复杂的对象类型,同样可以使用
Ref
泛型。例如,interface User { name: string; age: number; } const user: Ref<User> = ref({ name: 'John', age: 30 });
,这里user
是一个存储User
类型对象的响应式引用。
vue3中ts应用总结
- 组件定义与类型规范
defineComponent
函数的重要性- 在Vue 3中,
defineComponent
函数是结合TypeScript定义组件的关键。它能够更好地进行类型推断和检查,确保组件的正确性。例如,通过defineComponent
可以方便地在setup
函数中定义props
和emits
的类型,使组件的输入和输出更加明确。
- 在Vue 3中,
Props
类型定义的多种方式- 使用
interface
或type
来定义组件接收的属性(Props
)类型。这有助于在开发过程中对传入组件的属性进行严格的类型检查,避免因类型错误导致的问题。例如,interface Props { name: string; }
明确了组件接收一个名为name
的字符串类型属性。
- 使用
Emits
事件发射类型的定义- 对于组件向外发射的事件,同样需要定义类型。通过
interface
定义事件发射函数的类型,如interface ButtonEmits { click: () => void; }
,可以确保事件发射的参数和调用方式符合预期,增强组件之间交互的可靠性。
- 对于组件向外发射的事件,同样需要定义类型。通过
- 响应式数据处理与类型安全
ref
函数的应用与类型指定ref
用于创建基本类型(如数字、字符串、布尔值等)的响应式数据。可以通过Ref
泛型类型明确指定其内部存储的数据类型,如const count: Ref<number> = ref(0);
。这不仅保证了响应式数据的类型安全,还能在数据更新时提供正确的类型检查。
reactive
函数用于复杂对象响应式处理- 当处理复杂对象(包含多个属性的对象)时,
reactive
函数发挥作用。通过定义接口来描述对象结构,再使用reactive
创建响应式对象,如interface User { name: string; age: number; } const user: User = reactive({ name: 'John', age: 30 });
,使得对象的属性变化能够被响应式地更新到模板中,并且在访问和修改属性时遵循接口定义的类型规则。
- 当处理复杂对象(包含多个属性的对象)时,
- 计算属性(
computed
)与类型推断和指定- 计算属性是根据已有响应式数据计算得到新的值,并且也是响应式的。在TypeScript中,计算属性的类型通常可以自动推断,但在复杂情况下可以手动明确类型,如
const userInfo: Computed<string> = computed(() => {... });
。这有助于确保计算结果的类型符合预期,提高代码的可靠性。
- 计算属性是根据已有响应式数据计算得到新的值,并且也是响应式的。在TypeScript中,计算属性的类型通常可以自动推断,但在复杂情况下可以手动明确类型,如
- 事件处理与函数类型检查
- 在组件内部,事件处理函数需要遵循正确的类型定义。无论是组件自身的事件处理(如按钮点击事件),还是接收外部传入的事件处理函数作为属性,都要确保函数的参数和返回值类型正确。例如,在定义按钮组件的点击事件处理函数时,要保证函数的类型符合
click: () => void
这样的定义,防止在事件发射和接收过程中出现类型不匹配的情况。
- 在组件内部,事件处理函数需要遵循正确的类型定义。无论是组件自身的事件处理(如按钮点击事件),还是接收外部传入的事件处理函数作为属性,都要确保函数的参数和返回值类型正确。例如,在定义按钮组件的点击事件处理函数时,要保证函数的类型符合
- 组件组合与插槽类型考虑
- 组件组合的类型管理
- 当多个组件组合使用时,需要关注组件之间传递的数据和事件的类型。通过确保每个组件的
Props
和Emits
类型正确,可以构建出稳定可靠的组件树。例如,在一个包含标题组件和内容组件的布局组件中,要根据标题组件和内容组件的类型定义来正确传递属性和处理事件。
- 当多个组件组合使用时,需要关注组件之间传递的数据和事件的类型。通过确保每个组件的
- 插槽类型的潜在定义方式
- 对于带有插槽的组件,虽然Vue 3没有提供像
Props
那样详细的插槽内容类型定义机制,但可以通过v - slot
指令的语法和组件使用场景来约束插槽内容的类型。例如,如果组件主要用于包裹文本内容,那么可以期望插槽内容是字符串或者包含字符串的HTML元素,这有助于在一定程度上确保插槽使用的正确性。
- 对于带有插槽的组件,虽然Vue 3没有提供像
- 组件组合的类型管理
- 优势总结
- 提高代码可读性和可维护性
- TypeScript在Vue 3中的应用使得代码结构更加清晰。通过明确的类型定义,开发人员可以更容易地理解组件的输入输出、数据流向和功能逻辑。这对于新成员加入项目或者后期代码维护都非常有帮助。
- 增强类型安全,减少错误
- 在编译阶段就能够发现很多类型相关的错误,避免了在运行时因为数据类型不匹配而出现的问题。这大大提高了代码的质量和稳定性,减少了调试的时间和成本。
- 提高代码可读性和可维护性