【总结】Typescript 结合Vue3的写法

2023-11-13

目录

前言

一、结合写法

1. ref

2. reactive

3. defineProps

4. defineEmits

5. computed

6. 事件处理函数

7. html元素引用

8. 组件实例

二、拓展补充

1. keyof 操作符

2. typeof 操作符

3. InstanceType 工具类型


前言

Vue 3与TypeScript结合使用能够提供类型检查和智能提示,增强了代码的可靠性和可维护性。本文整理了项目开发时用到的结合写法,供学习和参考。

一、结合写法

1. ref

在原有的 ref() 之间加 <> ,并且在 <> 里跟ts类型。

ref() 也会隐式地从它的参数中推导类型。

const msg = ref<string>('hello')
​
import type { Ref } from 'vue'
const msg2: Ref<number> = ref(100)
​
type Todo = {
  id: number
  name: string
  done: boolean
}
const list = ref<Todo[]>([])
​
const list: Ref<Todo[]> = ref([])

2. reactive

在声明变量时,在 : 后跟ts类型。

reactive() 也会隐式地从它的参数中推导类型。

import { reactive } from 'vue'
​
// 推导得到的类型:{ title: string }
const book = reactive({ title: 'Vue 3 指引' })

​要显式地标注一个 reactive 变量的类型,我们可以使用接口

import { reactive } from 'vue'
​
interface Book {
  title: string
  year?: number
}
​
const book: Book = reactive({ title: 'Vue 3 指引' })

​不推荐使用 reactive() 的泛型参数,因为处理了深层次 ref 解包的返回值与泛型参数的类型不同。

3. defineProps

在原有的 defineProps() 之间加 <> ,并且在 <> 里跟ts类型。

// 注意这种方式无法设置可选参数的默认值
const props = defineProps<{
  name?: string
  phoneNumber: number
  userInfo: object
  tags: string[]
}>()

// 指定默认值
withDefaults(defineProps<{
  size?: number
  labels?: string[]
}>(), {
  size: 3,
  labels: () => ['default label']
})

上面写法太笨拙,可以使用 响应式语法糖 解构 + defineProps 就行

注意:目前需要 显式地选择开启 ,因为它还是一个实验性特性。

// vite.config.ts
export default defineConfig({
  plugins: [
    vue({
      reactivityTransform: true,
    }),
  ],
});
​
const { money, car = "宝马车" } = defineProps<{
  money: number
  car?: string
}>();

4. defineEmits

在原有的 defineEmits() 之间加 <> ,并且在 <> 里跟ts类型。

const emit = defineEmits(['change'])
const handleChange = () => {
  emit('change', 'itcast', '你好')
}
​
interface Emits {
  (e: "update:modelValue", value: string): void;
  (e: "change", value: string): void;
}
//定义控件事件
const emit = defineEmits<Emits>();
​
// 基于类型的声明
const emit = defineEmits<{
  (e: 'change', id: number): void;
  (e: 'update', value: string): void;
}>()

5. computed

computed() 会自动从其计算函数的返回值上推导出类型:

import { ref, computed } from 'vue'
​
const count = ref(0)
​
// 推导得到的类型:ComputedRef<number>
const double = computed(() => count.value * 2)
​
// => TS Error: Property 'split' does not exist on type 'number'
const result = double.value.split('')

​你还可以通过泛型参数显式指定类型:

const double = computed<number>(() => {
  // 若返回值不是 number 类型则会报错
})

6. 事件处理函数

<script setup lang="ts">
function handleChange(event) {
  // `event` 隐式地标注为 `any` 类型
  console.log(event.target.value)
}
</script>
​
<template>
  <input type="text" @change="handleChange" />
</template>

​没有类型标注时,这个 event 参数会隐式地标注为 any 类型。这也会在 tsconfig.json 中配置了 "strict": true"noImplicitAny": true 时报出一个 TS 错误。因此,建议显式地为事件处理函数的参数标注类型。此外,你可能需要显式地强制转换 event 上的属性:

function handleChange(event: Event) {
  console.log((event.target as HTMLInputElement).value)
}

7. html元素引用

模板引用需要通过一个显式指定的泛型参数和一个初始值 null 来创建:

<script setup lang="ts">
import { ref, onMounted } from 'vue'
​
const el = ref<HTMLInputElement | null>(null)
​
onMounted(() => {
  el.value?.focus()
})
</script>
​
<template>
  <input ref="el" />
</template>

8. 组件实例

<!-- MyModal.vue -->
<script setup lang="ts">
import { ref } from 'vue'
​
const isContentShown = ref(false)
const open = () => (isContentShown.value = true)
​
defineExpose({
  open
})
</script>

为了获取 MyModal 的类型,我们首先需要通过 typeof 得到其类型,再使用 TypeScript 内置的 InstanceType 工具类型来获取其实例类型:

<!-- App.vue -->
<script setup lang="ts">
import MyModal from './MyModal.vue'
​
const modal = ref<InstanceType<typeof MyModal> | null>(null)
​
const openModal = () => {
  modal.value?.open()
}
</script>

二、拓展补充

1. keyof 操作符

通过索引类型查询能够获取给定类型中的属性名类型。索引类型查询的结果是由字符串字面量类型构成的联合类型,该联合类型中的每个字符串字面量类型都表示一个属性名类型。

type Point = { x: number; y: number };
type P = keyof Point; // type P = 'x' | 'y'

​如果类型具有字符串或数字索引签名,则 keyof 将返回这些类型:

type Arrayish = { [n: number]: unknown };
type A = keyof Arrayish; // type A = number
​
type Mapish = { [k: string]: boolean };
type M = keyof Mapish; // type M = string | number
type Todo = {
  id: number;
  text: string;
  done: boolean;
}
​
const todo: Todo = {
  id: 1,
  text: "Learn TypeScript keyof",
  done: false
}
// extends 关键字约束 K 类型必须为 keyof T 联合类型的子类型。 'id' | 'text' | 'done'
function prop<T extends object, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}
​
const id = prop(todo, "id"); // const id: number
const text = prop(todo, "text"); // const text: string
const done = prop(todo, "done"); // const done: boolean

2. typeof 操作符

用于获取一个值的类型信息。typeof操作符有两种主要的使用方式:

  • typeof表达式:用于获取一个值的类型字符串。
const num = 42;
const typeOfNum = typeof num; // 类型为 "number"

const obj = { name: 'Alice', age: 25 };
const typeOfObj = typeof obj; // 类型为 "object"

注意:typeof操作符返回的是一个字符串字面量,表示该值的类型。常见的返回值包括 "number"、"string"、"boolean"、"object"、"function"等。

  • typeof类型守卫:用于在条件语句中判断一个变量的类型。
function printLength(value: string | number) {
  if (typeof value === 'string') {
    console.log(value.length); // 在这个条件块中,value被推断为 "string" 类型
  } else {
    console.log('Value is not a string.');
  }
}

在上述代码中,通过使用typeof进行类型检查,可以在不使用显式类型断言的情况下,根据不同的类型执行不同的代码逻辑。

需要注意的是,typeof操作符的结果在某些情况下可能比较特殊,例如:

  1. typeof null 的结果是 "object",这是由于历史原因造成的。
  2. 对于函数类型,typeof会返回 "function"。

3. InstanceType 工具类型

该工具类型能够获取构造函数的返回值类型,即实例类型。这里面的T必须是一个构造函数。

class C {
  x = 0;
}
type T0 = InstanceType<typeof C>;         // C

type T1 = InstanceType<new () => object>; // object

type T2 = InstanceType<any>;              // any

type T3 = InstanceType<never>;            // any

type T4 = InstanceType<string>;           // 编译错误
type T5 = InstanceType<Function>;         // 编译错误

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【总结】Typescript 结合Vue3的写法 的相关文章

  • JavaScript 添加布尔值

    console log true true 2 console log typeof true true number console log isNaN true true false 为什么两个布尔类型相加会产生一个数字 我有点理解 如
  • 显示具有多个父代的 D3 树

    我目前有this http bl ocks org mbostock 4339083图已实现 我希望在描述具有多个父节点的子节点时保持结构和可折叠性 有没有办法做到这一点 我研究了力图 但我也想保留一组层次结构 这意味着 1 级的父级可以有
  • 位置特征检测:固定

    我正在尝试找到一个脚本来检测设备是否放置position fixed元素相对于视口而不是整个文档 目前 标准桌面浏览器和 Mobile Safari 适用于 iOS 5 都是这样做的 而 Android 设备则相对于整个文档放置固定元素 我
  • 使用 Angular 指令禁用文本选择

    我正在学习 JavaScript 和 AngularJS 我想使用 Angular Directive 禁用文本选择 我有该函数的 JavaScript 代码 function clearSelection if document sele
  • 从回调中访问状态

    我在从回调访问组件状态时遇到问题 国家的价值num更改正确 但此类更改对于加载时定义的回调函数不可见 import React useState from react class MyObject callback gt void cons
  • nodejs (libuv) 事件循环是否在一个阶段(队列)中执行所有回调,然后再进入下一阶段或以循环方式运行?

    我正在研究 Node js 中 libuv 提供的事件循环 我遇到了关注 Deepal Jayasekara 的博客 https blog insiderattack net event loop and the big picture n
  • IntersectionObserver是否支持水平滚动观察?

    我制作了几个垂直滚动 IntersectionObserver 模块 但我对水平滚动感兴趣 根将是 div 观察目标将是 img 我想观察当 img 放大但 div 保持视口宽度时的变化 我什至不确定移动 Safari 是否会将缩放后的图片
  • JavaScript 验证和 PHP 验证?

    我正在使用 jquery 验证插件来验证空表单 我还应该在 PHP 中检查一下以确保 100 正确吗 或者用 javascript 验证就可以了 谢谢 您应该始终在服务器上进行验证 如果用户以某种方式不使用 Javascript 提交表单
  • JavaScript 继承;调用和原型

    要在Javascript中实现继承 通常需要执行以下两个步骤 假设我有一个基类 Animal var Animal function name this name name 我现在想从中派生一个子类 Dog 所以我想说 var Dog fu
  • JavaScript 中的 Promise 有什么意义?

    一个承诺是一个 可能现在可用 或将来可用 或永远不可用的值 来源 MDN 假设我有一个想要处理图片的应用程序 图片已加载 例如在算法在后台使用它之后 或某种其他类型的延迟 现在我想检查一下图片是否可以在future 通过使用承诺 而不是回调
  • 如何使用角度材料在具有可扩展行的表格中创建嵌套垫表

    我有以下数据 id c9d5ab1a subdomain wing domain aircraft part id c9d5ab1a info mimetype application json info dependent parent
  • 计算三次贝塞尔曲线的弧长、曲线长度。为什么不工作?

    我正在用这个算法计算弧长 三次贝塞尔曲线的长度 function getArcLength path var STEPS 1000 gt precision var t 1 STEPS var aX 0 var aY 0 var bX 0
  • 如何始终将焦点保持在文本框中

    我创建了一个包含两个 div 的 HTML 页面 左侧的 div 页面的 90 是 ajax 结果的目标 右侧的 div 页面的 10 包含一个文本框 该页面的想法是在文本框中输入零件编号 通过条形码扫描仪 并显示与该零件编号匹配的绘图 显
  • Google Maps API (v3) 添加/更新标记

    编辑 它现在可以工作 但如果用户不允许或没有基于位置的服务 则不会加载 请参阅 jsfiddle 示例接受的答案评论 我已经浏览了一些教程和问题 但我无法安静地理解正在发生的事情 或者在这种情况下 没有发生 当用户单击链接时 我正在加载地图
  • Rails 3.1+ 的 Jasmine 与 Mocha JavaScript 测试 [已关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我对茉莉花有经验并且非常喜欢它 有谁有 Jasmine 和 Mocha 的经验 特别是 Rails 的经验吗 我想知道是否值得转用 我已经在 J
  • 使用 next.js 进行服务器端渲染与传统 SSR

    我非常习惯 SSR 意味着页面得到完全刷新并从服务器接收完整 HTML 的方法 其中根据后端堆栈使用 razor pub other 进行渲染 因此 每次用户单击导航链接时 它只会向服务器发送请求 整个页面将刷新 接收新的 HTML 这就是
  • 有没有办法使用 ko.observableArray 作为地图?

    有没有办法使用ko observableArray http knockoutjs com documentation observableArrays html像地图 字典一样 例如 var arr ko observableArray
  • Flot 库将 y 轴设置为最小值 0 和最大值 24

    如何将 y 轴设置在 0 到 24 的范围内 这是我的代码 j plot j placeholder d1 xaxis mode time min new Date 2010 11 01 getTime max new Date 2011
  • 如何从 json 文件创建模型? (ExtJS)

    这是我想使用 json 文件创建的模型 Ext define Users extend Ext data Model fields name user id type int name user name type string 为了根据服
  • 如何通过索引访问 JSON 对象中的字段

    我知道这不是最好的方法 但我别无选择 我必须通过索引访问 JSONObject 中的项目 访问对象的标准方法是只写this objectName or this objectName 我还找到了一种获取 json 对象内所有字段的方法 fo

随机推荐

  • c:Bubble Sort

    file SortAlgorithm h brief 业务操作方法 VSCODE c11 author geovindu Geovin Du date 2023 09 19 ifndef SORTALGORITHM H define SOR
  • Opencv dft & idft

    Load an image cv Mat inputImage cv imread argv argc 1 0 Go float cv Mat fImage inputImage convertTo fImage CV 32F FFT st
  • HTML的无序列表、有序列表、自定义列表

    HTML的无序列表 1 无序列表是一个项目的列表 此列项目使用粗体圆点 典型的小黑圆圈 进行标记 无序列表始于 ul 无序列表 ul type disc li HTML li li CSS li li li ul ul
  • 函数的传递方式&不定长参数&参数解包

    文章目录 1 函数简介 2 函数的参数 2 1 形参和实参 2 2 函数的传递方式 2 2 1 位置传参 2 2 2 关键字传参 2 3 函数的实参类型 2 4 不定长参数 2 5 参数的解包 1 函数简介 函数也是一个对象 函数用来保存一
  • C++ 模板特例化

    文章目录 介绍 函数模板特例化 类模板特例化 介绍 模板作为C 泛型编程的基础十分重要 其使得一份代码能用于处理多种数据类型 而有些时候 我们会希望对一些特定的数据类型执行不同的代码 这时就需要使用模板特例化 template specia
  • Echarts 渐变色

    series i line itemStyle normal color Color Function default 自适应 图形的颜色 默认从全局调色盘 option color 获取颜色 颜色可以使用 RGB 表示 比如 rgb 12
  • Java技术栈,从入门到放弃,废了废了

    Java技术路线 应用框架 后端 Spring家族 Spring IoC AOP Spring MVC Spring Boot 自动配置 开箱即用 整合Web 整合数据库 事务问题 整合权限 Shiro Spring Security 整合
  • 开放集识别

    0 摘要 1 到目前为止 在计算机视觉中 几乎所有基于机器学习的识别算法的实验评估都采用了封闭集识别的形式 即在训练时已知所有测试类 对于视觉应用来说 一个更现实的场景是开放集识别 在训练时存在不完整的世界知识 在测试时未知的类可以提交给算
  • Vscode 打开文件注释中文乱码解决如下

    安装插件 ext install gbktoutf8 搜索encoding
  • 【LINUX计算机大白平凡学习linux之路】

    计算机大白平凡学习 之路 千里之行 始于足上 只有基础扎实 思路清析 写脚本才没有问题 多看一些牛人大咖写的脚本 看人家的思路与结构 会收益良多 一起努力学习吧 Linux是Torvalds先生所开发出来的 基于GPL的版权宣告之下 可以在
  • 神经网络优化(初始化权重)

    使隐藏层饱和了 跟之前我们说的输出层饱和问题相似 对于输出层 我们用改进的cost函数 比如cross entropy 但是对于隐藏层 我们无法通过cost函数来改进 更好的方法来初始化权重 因为传统的初始化权重问题是用标准正态分布 均值为
  • CentOS7.6 MySql 5.7.34安装部署

    一 卸载Mysql 查看系统是否安装默认的mysql rpm qa grep i mysql 如有 进行卸操作 rpm e nodeps 确认是否卸载完成 whereis mysql cd find name mysql cat etc p
  • 一种新型神经网络正在帮助物理学家应对数据分析的艰巨挑战

    来源 ScienceAI 本文约3000字 建议阅读5分钟 现在 在计算端 计算机科学往往处于领先地位 假设你有一本一千页的书 但每一页只有一行文字 你使用扫描仪提取书中包含的信息 这个特定的扫描仪系统地扫描每一页 一次扫描一平方英寸 要花
  • crmeb v4.3部署流程

    运行环境 CRMEB v4支持Lunix windows服务器环境 需要PHP7 1 7 3 版本支持 可运行于包括Apache和nginx在内的多种WEB服务器和模式 支持Mysql数据库 引擎用InnoDB 框架本身没有什么特别模块要求
  • Pyinstaller 打包.py生成.exe的方法和报错总结

    Pyinstaller 打包 py生成 exe的方法和报错总结 简介 有时候自己写了个python脚本觉得挺好用想要分享给小伙伴 但是每次都要帮他们的电脑装个python环境 虽然说装一下也快 但是相对来说效率还是不高 要是能将python
  • 【AI &Data Science】第 1 章分析性思维与 人工智能驱动的企业

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • DHCP设置之起始地址与结束地址

    路由器设置ip地址 subnet mask dhcpstart dhcpend时 后台应该如何判断 get data ipstart websGetVar wp T start T ipend websGetVar wp T end T i
  • do while(0)的作用

    在嵌入式开发的过程中 我们经常可以在一些优秀开源代码的头文件里发现一些宏定义使用了do while 0 语句 也许你会疑惑do while 0 中的代码不就是只执行一次吗 为什么还要多此一举使用do while 0 循环结构去包裹呢 实际上
  • 卷积、池化、激励函数的顺序

    以下内容为个人的看法 顺序 卷积 池化 激励函数 我们知道卷积肯定是在第一层 毕竟 wx b wx b 就是卷积操作 那为什么池化要在激励函数之前呢 原因解析 假设激励函数是 relu 激励函数 并假设我们卷积后的值为 3 2 1 2 对于
  • 【总结】Typescript 结合Vue3的写法

    目录 前言 一 结合写法 1 ref 2 reactive 3 defineProps 4 defineEmits 5 computed 6 事件处理函数 7 html元素引用 8 组件实例 二 拓展补充 1 keyof 操作符 2 typ