TypeScript


TypeScript

这篇文章主要总结了TypeScript

一.TypeScript 概述

是什么?TS是微软开发的编程语言,他是JS的超集,可以在任何运行JS的地方运行
官方文档中文文档

TypeScript = Type + JavaScript(在 JS 基础之上,为 JS 添加了类型支持/类型检测)

1.优势:

背景:
JS是弱类型语言,而在代码中很多错误都是类型错误,
他不像其他强类型语言一样有类型检测,比如JAVA,因此出现了TS

1.发现错误的时机更早,即TS在编译时,即代码执行前就会出现类型检测

2.代码提示,JS代码没有代码提示,需要插件才能支持代码提示

3.支持最新的ECMAScript语法

4.Vue3源码使用TS重写,React 也与 TS 完美配合

2.安装并编译TS

1.安装命令:npm i -g typescript 或者 yarn global add typescript
2.验证是否安装成功:tsc –v(查看 TypeScript 的版本)

3.创建 hello.ts 文件(注意:TS 文件的后缀名为 .ts)。
4.将 TS 编译为 JS:在终端中输入命令,tsc hello.ts(此时,在同级目录中会出现一个同名的 JS 文件)。
5.执行 JS 代码:在终端中输入命令,node hello.js。

说明:所有合法的 JS 代码都是 TS 代码,有 JS 基础只需要学习 TS 的类型即可。
注意:由 TS 编译生成的是 JS 文件,生成的代码中就没有类型相关的信息了。

3.创建Vue TS项目

在基于 Vite 的项目中可以直接验证 TS 代码结果,因为已经配置好了 TS 环境。

# npm 6.x
npm create vite@latest my-vue-ts-app --template vue-ts

# npm 7+, extra double-dash is needed:
npm create vite@latest my-vue-ts-app -- --template vue-ts

# yarn
yarn create vite my-vue-ts-app --template vue-ts

# pnpm
pnpm create vite my-vue-ts-app --template vue-ts

二.TS基础

1.原始类型

语法:const 变量名:数据类型 = 与数据类型匹配的值

与数据类型匹配的值的意思时,比如数据类型写的数字,那么你的值必须写数字

const num: number = 18
console.log(num.toFixed(2))

const str: string = '龚贤龙'
const b: boolean = true

const u: undefined = undefined

const n: null = null

//const big:bigint = 888888888888888n
//console.log(big)

const sym: symbol = Symbol()

2.数组类型

语法1:const 变量名: Array<number> = [ 1, 2, 3 ]

语法2:const 变量名: number[] = [ 1, 2, 3, 4 ]

这两句代码表示该变量现在为数字组成的数组

const list: Array<number> = [ 1, 2, 3 ]
const list1: number[] = [ 1, 2, 3, 4 ]

3.联合类型

语法:const 变量名: (number | string)[] = [ 1, 2, '3', '4' ]

这句代码表示该变量限制类型为数字和字符串组成的数组

const arr: (number | string)[] = [ 1, 2, '3', '4' ]
const arr1: Array<number | string> = [ 1, 2, '3', '4' ]

4.类型别名

语法:type 类型别名 = 数据类型
let 变量名 :类型别名 = 数据

type uname = String
let zname: uname = '龚贤龙'

type arr2 = (number | string)[]
const arr3: arr2 = [ 1, 2, 3, 'gh', 'sf' ]
console.log(arr3)

5.函数类型

函数如果不指定返回值,默认void类型
主要是分别指定参数与返回值的类型

方式1

//普通函数声明
function sum(num1: number, num2: number): number {
	return num1 + num2
}
sum(1, 3)

//函数表达式
const sum1 = (num1: number, num2: number): number => {
	return num1 + num2
}
sum1(1, 4)

方式2

//同时指定参数与返回值,只适用于函数表达式
type TFn = (num1: number, num2: number) => number
const sum3: TFn = (num1, num2) => {
	return num1 + num2
}
sum3(5, 8)

6.void类型

作用:当一个函数没有给他的返回值指定类型时,它默认是void类型

function ok(): void {}

7. ? 可选参数

注意1:可选参数必须放在必选参数后面

function slice(start?: number, end?: number): any[] {
	console.log(start, end)
	return []
}
slice()
slice(1)
slice(1, 2)

注意2:数组默认参数 不能和可选参数一起使用

function slice1(start: number = 10, end?: number): any[] {
	console.log(start, end)
	return []
}
slice1()
slice1(1)
slice1(1, 2)

8.对象类型指明参数类型

const obj: { name: string; age: number } = {
    name: '龚贤龙',
    age: 29
}

或者

const o = {
	name: '龚贤龙',
	age: 29
}
const obj: { name: string; age: number } = o 

9.interface接口与extends继承

interface Point2D {
    x: number
    y: number
}
// 使用 `extends`(继承)关键字实现了接口 Point3D 继承 Point2D
// 继承后,Point3D 就有了 Point2D 的所有属性和方法(此时,Point3D 同时有 x、y、z 三个属性)
interface Point3D extends Point2D {
    z: number
}

10.interface与type

相同点:
1.都可以描述对象和函数
2.都可以进行类型扩展,但语法不一样

//interface用的extends
//type用的&符号,形成的叫交叉类型

不同点:
1.type可以描述任意类型,interface做不到
2.相同的interface会合并,相同的type会报错

总结
一般用于interface描述对象,用type来描述类型之间的关系

11.字面量类型

字面量类型往往配合联合类型一起使用

使用场景:用来表示一组明确的可选值列表,比如在贪吃蛇游戏中,
游戏方向的值只能是上、下、左、右中的一个。

type Direction = 'up' | 'down' | 'left' | 'right'
function changeDirection(direction: Direction) {
    console.log(direction)
}
changeDirection('up') // 调用函数时,会有类型提示

解释:参数direction的值只能是 up/down/left/right 中的任意一个。

优势:相比于 string 类型,使用字面量类型更加精确、严谨

12.类型断言 as

往往把一个宽泛的类型断言为一个更加具体的类型,为使用这个更加具体的属性和方法

语法1:const oLink = document.getElementById('link') as HTMLAnchorElement

语法2:const oLink = <HTMLAnchorElement>document.getElementById('link')

第二种语法了解即可

13.特殊类型 any/unknown/never

1.unknown是更加安全的any类型(有一些可能导致程序的报错的操作会提示出来)

2.任何类型都可以给any,any也可以给任何类型

3.任何类型都可以给unknownunknown只能给unknownany

4.unknown一般配合类型收窄一起使用(typeof 可以类型收窄,as断言可以类型收窄)

5.never不可能实现的类型

type Test = number & string
// 也可以当做函数的返回值,表示不会执行到头
function test(): never {
    throw new Error('Error')
}

三.TS泛型

1.泛型别名

定义类型别名后,加上 <类型参数> 就是泛型别名语法,
使用的时候传入具体的类型即可,然后类型别名内就可以使用这个类型参数。

// 对后台返回的数据进行类型定义
type User = {
    name: string;
    age: number;
}

type Goods = {
    id: number;
    goodsName: string;
}

type Data<T> = {
    msg: string;
    code: number;
    data: T
}

// 使用类型
type UserData = Data<User>   //把user作为参数传递给T
type GoodsData = Data<Goods>   //把goods作为参数传递给T

2.泛型接口

接口也可以配合泛型来使用,以增加其灵活性,增强其复用性

interface User<T> {
    name: T
    age: number
}
const user: User<string> = {
    name: 'ifer',
    age: 18,
}
//数组泛型接口的实现
// 这其实也是通过泛型接口的形式来定义的数组类型
const arr: Array<number> = [1, 2, 3]
// 模拟实现
interface IArray<T> {
    // 索引签名
    // 只要是 number 类型的键都可以出现在数组中,或者说数组中可以有任意多个元素
    // 同时也符合数组索引是 number 类型这一前提
    [key: number]: T
}

const arr: IArray<string> = ['a', 'b']

3.泛型函数

定义时宽泛、不确定的类型,需要使用者去主动传入

function id<Type>(value: Type): Type {
    return value
}
const num = id<number>(10)
const str = id<string>('a')
//就是把<number>传给<type>

//简化
let num = id(10) // 省略 <number> 调用函数
let str = id('a') // 省略 <string> 调用函数

4.泛型工具

Partial

作用:都变为可选,加上?

type Props = {
    id: string
    children: number[]
}

type PartialProps = Partial<Props>     //Partial 可选

Required

作用:都变为必选,去掉?

type Props = {
    id?: string
    children?: number[]
}

type PartialProps = Required<Props>     //Requored 必选

ReadOnly

作用:变为只读

type Props = {
    id: string
    children: number[]
}
type ReadonlyProps = Readonly<Props>   //Readonly 只读

let props: ReadonlyProps = { id: '1', children: [] }
props.id = '2' 
//此时的props.id = '2'是无法将id改为2的,因为设置了只读的泛型工具,只允许你读取,无法修改

Pick

作用:选择一组属性构造新类型,过滤掉不使用的属性

两个变量:1.表示选择谁的属性,2.表示选择哪几个属性

interface Props {
    id: string
    title: string
    children: number[]
}
// 摘出 id 和 title
type PickProps = Pick<Props, 'id' | 'title'>

Omit

作用:与pick相反,过滤掉选择的属性,使用不选择的属性

// 排除 id 和 title
type OmitProps = Omit<Props, 'id' | 'title'>

文章作者: 冷杨威
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 冷杨威 !
  目录
-->