ts概述、ts环境准备和编译、ts类型声明

news/2024/11/7 22:35:40/

文章目录

  • 1. ts概述
  • 2. ts环境准备和编译
  • 3. ts类型声明
    • 3.1 布尔值
    • 3.2 数字类型
    • 3.3 字符串类型
    • 3.4 any和unknown
    • 3.5 void、null、undefined
    • 3.6 never类型
    • 3.7 字面量类型
    • 3.8 枚举类型
    • 3.9 object对象类型
    • 3.10 数组
    • 3.11 元组
    • 3.12 自定义类型type
    • 3.13 联合类型
    • 3.14 交叉类型
    • 3.15 类型断言


1. ts概述

TypeScript 由微软开发的自由和开源的编程语言,它可以在任何任何操作系统上运行。可以理为TypeScript是JavaScript 的超集,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。

在这里插入图片描述

Ts和Js最大的不同,在于Ts有类型检查。在一些大型项目,多人合作开发的项目中,类型的统一是一件非常困难的事件,有了Ts的加持,可以方便类型的统一。

TS浏览器或一个js运行环境是不支持,需要把ts转为js,才能运行。

在这里插入图片描述

一般的人少开发的项目,不要用,用它反而降低开发速度,但是如果多人开发,或项目有可能变大,建议还是一步到位,用上ts。

2. ts环境准备和编译

ts不能直接运行,需要把ts转成js来运行,需要ts编译器 typescript 最新版本为4.x,需要全局安装一 typescript 编译器:npm i -g typescript

检查一下,是否安装成功tsc --version,如果能看到版本号,则表示安装成功。

将 ts 文件转换为 js 文件命令:

// 转换  tsc xx.ts 就可以了  -w 只能此ts文件有修改它会自动编译 --outDir 指定编译后的js放到哪里去// tsc src\1.ts --outDir dist -w

进入到 dist 目录下,运行文件:node 1.js

3. ts类型声明

TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了自己特有的一些类型。

  • 类型声明(手动给变量或参数指定类型)

    类型声明是TS非常重要的一个特点,通过类型声明可以指定TS中变量(参数、形参)的类型,当为变量赋值时,TS编译器会自动检查值是否符合类型声明,符合则赋值,否则报错,类型声明给变量设置了类型,使得变量只能存储某种类型的值。

  • 自动类型(类型推论[ts很重要的一个特性])

    当对变量的声明和赋值是同时进行的,TS编译器会自动根据右边的值来给左边的变量赋对应的类型。从右决定左类型【场景最多】

注意:

  1. ts中默认提供的内置类型,在指定时一定要全小写,例如:

    string

    number

    boolean

    object

    null

    undefined

    any

    unknown

  2. 自定义类型时,可能是大写

3.1 布尔值

// 手动类型声明
// 声明一个变量,指定它的类型为boolean,此时,此变量只能赋值布尔类型的值
let arg:boolean
arg = true// 自动类型声明
// 右侧决定左侧类型  直接给变量赋值,ts编译器会在编译时,根据右侧的值类型来赋值给左侧变量类型
// 工作中用的多,如,给一个默认值同时就给当前的这个参数一个类型
let arg1 = true

3.2 数字类型

// 先声明类型 ,再赋值
let arg:number
arg=1// 自动类型赋值
let arg1 = 2

也可以复制其他进制的数字类型:

  • let decLiteral: number = 6; // 十进制
  • let hexLiteral: number = 0xf00d; // 十六进制
  • let binaryLiteral: number = 0b1010; // 二进制
  • let octalLiteral: number = 0o744; // 八进制

3.3 字符串类型

// 先声明类型 ,再赋值
let arg: string
arg = 'hello'// 自动类型赋值
let arg1 = 'hello'

3.4 any和unknown

any和unknown,它俩都表示任意类型,unknown 是 ts3.x 后提供的,而 any 一开始就有。

两者区别:

我们可以对any类型进行任何操作,ts不需要进行检查类型,赋值的类型对于ts编译器来说就不重要了,相当于在ts中写js,所以少用,类型不安全。

unknown是any的安全类型,unknown只能被赋值unknown本身,unknown本身赋值是随意的,但是在调用的时候,会进行类型检查 ,所以需要类型断言,才能用。unknown一般会它来完成类型的转换工作:string类型 => unknown => number类型。

// === any 任意类型
let arg1: any
arg1 = 1
arg1 = 'zhangsan'
arg1 = true
// arg1它是一个any,调用它的print方法
arg1.print()
arg1.length// === unknown 任意类型
let arg2: unknown
arg2 = 1
arg2 = 'zhangsan'
arg2 = true
// 在any中是可以,ts不检查,js通过,但是unknown用时类型的检查,看一下当前类型中有没有此方法或属性 没有print报错
// arg2是一个unknown,未知类型,不知道现在有没有print方法,不知道就报错,unknown比any要安全的地方
// 报错
// arg2.print()
// arg2.length

3.5 void、null、undefined

void:

它表示没有任何类型, 声明一个void类型的变量没有什么大用,因为你只能为它赋予undefined,一般多用于函数返回值指定。

undefined和null:

两者各自有自己的类型分别叫做undefined和null。 和 void 相似,它们的本身的类型用处不是很大。

// void 一般用于【函数返回值类型中指定】,表示当前的函数没有返回值,也可以用来指定变量,表示此变量为undefined
// null类型/undefined
// void类型 了解知道它还可以赋值给变量
let arg1: void
arg1 = undefined// 此函数没有返回值,如果你不指定函数的返回值,ts会根据当前函数的结果来推断出它的返回值
// 在工作中,一般函数非必要的情况下,一般不指定返回值类型,让它自动推断出来
// 没有返回值的几种情况:
function print(): void {console.log(123)
}function print(): void {}function print(): void {return
}
function print(): void {return undefined
}// null类型
// 如果要把一个变量声明为null类型
let arg2: null
arg2 = null// undefined类型
let arg3: undefined
arg3 = undefined

3.6 never类型

never类型表示的是哪些永不存在的值的类型,此类型多用于ts的底层实现中使用,在应用层级中,一般用不到。

在底层中的用法类似这样:type EType = xx extends yy ? string : never

// 类型保护 typeof得到类型  instanceof是不是它的实例
function print(name: string) {if (typeof name === 'string') {console.log(name.length, '字符串')} else {// ts中,此句,写和不写没有区别,不会执行到这里  never在底层,表示console.log(name)}
}
// 这样写在ts编译时会报错,不通过
// print(123)

never类型是unknown类型的子类型:

// never类型它是unknown类型的子类型
// extends在ts中理解为,never定义的属性或方法在 unknown全部都要有,则为真
// extends判断一个类型是否是别的类型的子类型
type NeverType = never extends unknown ? string : boolean
let a: NeverType
a = '1'

3.7 字面量类型

声明一个变量,变量的值,它只能在规定的几个值范围中去选择其中之一来赋值。

// 类型定义在变量的后面用冒号,然后紧跟定义的类型
// 字面量类型无法进行类型模块化,如果想要进行模块化,可以使用枚举类型
let arg: 'aa' | 1 | true
arg = 1

3.8 枚举类型

指定的范围中去选择值。定义一个枚举类型,可以指定的元素的值,也可以不指定,如果不指定,默认值为数字,值从0开始,累加下去。

枚举类型可以通过 export 进行模块化导出。

定义一个枚举类型,不指定元素的值:

// 可以把枚举,定义为数组
enum Color {// 0red,// 1green,// 2blue,// 3pink,// 4yellow
}
// 如果指定的一个变量它的类型为枚举类型,则在赋值时,最好是使用 枚举类型.元素 进行赋值
let c: Color
c = Color.green
console.log(c); // 1// 类型转换出来的都为数字,所以在给变量赋值为数字时,不会报错,类型对的,可以成功运行
c = 10
console.log(c); // 10

定义一个枚举类型,指定元素的值:

enum Color {red = 'red',green = 'green'
}
let c: Color
c = Color.green
console.log(c) // green

定义一个枚举类型,一部分指定值,一部分不指定值:

// 如果你指定值,它的类型为数字,则下面的元素会从上一个元素的数字+1开始,下一个元素无需手动指定
// 如果你赋值是非数字,则下一个元素需要手动给值,直到遇到上一个元素值为数字为止
enum Color {// 0red,// greengreen = 'green',// 10blue = 10,// 11pink,// 12yellow
}
let c: Color
c = Color.pink
console.log(c) // 11

枚举类型小案例:

// redux   action
enum ActionEnumType {addNum = 'addNum',decrNum = 'decrNum'
}
const reducer = (state = { num: 1 }, action: { type: ActionEnumType; payload: any }) => {return state
}
// 使用了枚举类型 ,把原来的type给限定义范围,只能在规定的规范中去使用值
reducer({ num: 100 }, { type: ActionEnumType.addNum, payload: [] })

3.9 object对象类型

使用 object 规定对象类型:

在工作中,一般不要轻易给一个参数或变量一个object类型,它虽然会有类型检查,但是它的范围有点的广,比如下面这个例子,我的目的是定义一个{id:1}的对象,但是当赋值为[]时,类型检查也会通过。

// 在工作中,一般不要轻易给一个参数或变量一个object类型,它虽然会有类型检查,但是它的范围有点的广
let arg: object
arg = []
arg = { id: 1 }

使用{属性:类型,属性:类型}方式规定对象类型:

let arg: { id: number; name: string }
arg = { id: 1, name: '张三' }

定义可选属性:

// 对象中的属性,有一些属性它是可以定义,也可以不定义 可选属性 用?
// ?: 可选属性,在赋值时,可以定义此属性,也可以不定义,不会报错
let arg: { id: number; name: string; age?: number }
arg = { id: 1, name: 'aaa', age: 10 }
arg = { id: 1, name: 'aaa' }

定义动态属性:

// 没有事前定义的属性,它的名称是不确定,数据类型不确定,现在需要obj对象它可以定义此新添加属性
// key的名称我不知道,但是类型我是确定的,string  key它就是变量
// value值,类型不确定,因为它什么可能都会存在所以规定为any类型
// let arg = {id:1,name:'aaa'}
// arg['sex'] = '0'
// arg['a'] = 1
// arg['b'] = true
// console.log(arg)// 动态属性,可能还存在多个
let arg: { id: number; name: string; [key: string]: any }
arg = { id: 1, name: 'aaa' }
arg['sex'] = '0'
arg['a'] = 1
arg['b'] = true
arg['aa'] = []
console.log(arg) // { id: 1, name: 'aaa', sex: '0', a: 1, b: true, aa: [] }

对象兼容性:

// 对象的兼容性  --- 【一个类型是另一个类型的子集/范围广的赋值给范围少的】 如果你想把一个类型赋值给另一个类型,
// 则前提是,你当前类型中所有的属性在接受变量类型中都有
// 接受者是赋值者的超集就可以
let arg1: { id: number; name: string; age: number }
let arg2: { id: number; name: string }
let arg3: { id: number }
arg1 = { id: 1, name: '张三', age: 7 }
arg2 = { id: 1, name: '张三' }
arg3 = { id: 1 }
// arg2赋值给arg1,不行,会报错
// arg1 = arg2
// arg1赋值给arg2,可行,不会报错
arg2 = arg1
// 不会报错
arg3 = arg2

3.10 数组

// 如果直接赋值一个空数组,推导出来的为一个any[]
let arg = []// 如果赋值一个数字类型的数组,推导出来的为一个 number[]
// number[]
let arg1 = [1, 2]// 规定数组类型方式1:
// 定义一个指定类型的数组   指定类型,没有指定长度,它称为数组
let arg2: number[] = [1, 2, 3]// 规定数组类型方式2:
// Array<类型> 泛型 定义指定类型的数组
let arg3: Array<string> = ['a', 'b']

3.11 元组

let arg: [number, string]
arg = [1, 'a']// 注意:元组只能是定义出来的,推导出来的,都为数组,比如下面这种写法,表示一个数组
let arg2 = [1, 'a']

3.12 自定义类型type

自定义类型给变量用:

// 通过type关键字完成自定义类型的定义  type定义的类型,在同一个模块下面,名称是不能重名的
// 定义类型给变量用
type UserType = { id: number; name: string; age: number }
let arg1: UserType
let arg2: UserType
let arg3: UserType

自定义类型给函数用:

// 定义一个类型来限制函数的参数类型和返回的类型
// 定义的参数类型限制,它只限制类型,不限制你所定义的形参的名称
// 写法1:
// type FnType = { (a: string, b: number): string }
// 写法2:
type FnType = (a: string, b: number) => string
const fn: FnType = (id: string, name: number) => {return 'hello'
}

限制构造函数参数的类型:

// new (id: number) 限制构造函数参数的类型,表示当前一定它是一个类,可以被实例化,且能用new来实例,并且限制了它的构建函数参数类型
// 注意:自定义类型也可以进行模块化导出
export type PersonType = { new (id: number): void }class Person {constructor(id: number) {}
}let p: PersonType = Person

3.13 联合类型

多个类型可以选择的,类型和类型之间用|隔开

// ----------------------- 联合类型  多个类型可以选择的 类型和类型之间用 | 隔开
// 此变量可以赋值的类型可以是number,也可以是string,还可以是boolean
// let arg: number | string | boolean | string[]
// 联合类型中有unknown或any ,任何的类型和它俩联合都是转为 unknown或any
// let arg: string | unknown // unknown
// let arg: string | any // any
// 联合类型中有 never 类型,它是不会生效,写和不写没有区别,相当于类型不存在,类型检查时也不会有
// number | string | boolean | string[],这个类型相当于下面这种写法
let arg: number | string | boolean | string[] | never

3.14 交叉类型

取两个类型的交集。

普通变量进行交叉:

type type1 = number | string
type type2 = string | boolean
// string
type type3 = type1 & type2

如果是对象类型,进行交叉,得到是一个并集操作:

type type1 = { id: number; name: string }
type type2 = { age: number }
// {id:number,name:string,age:number}
type type3 = type1 & type2
let t: type3 = { id: 1, name: 'aa', age: 1 }

注意:对象类型的交叉,最好保证属性名如果重名,则类型相同或是一个联合类型

如果对象类型中,遇到属性的名称和类型相同的情况,则会直接进行合并,例如下面的例子直接会把id:number合并为一个类型限制:

type type1 = { id: number; name: string }
type type2 = { id: number; age: number }
// {id:number,name:string,age:number}
type type3 = type1 & type2
let t: type3 = { id: 1, name: 'aa', age: 1 }

如果对象类型中,遇到属性的名称相同,但类型不相同的情况,则会把类型不同的属性限制为 never 类型:

type type1 = { id: number; name: string }
type type2 = { id: string; age: number } // 把 id 的类型变成 never 类型
// 注意:type type2 = { id: number|string; age: number } ,这种情况下,id 的类型为 number
// {id:never,name:string,age:number}
type type3 = type1 & type2
// let t: type3 = { id: 1, name: 'a', age: 20 } // 报错,id无法来赋值

使用交叉类型来扩展属性:

// 假设 Slice 对象是通过npm安装的一个reduxjs中的类型
type Slice = {name: string
}// 通过交叉类型扩展属性
type ExtSlice = Slice & {username: string
}const userSlice: ExtSlice = {name: 'aa',username: 'admin'
}// 小案例,假设有下面这样的场景,我们可以通过交叉类型实现属性的扩展
import { Request, Response } from 'express'
const express = require('express')
const app = express()
app.listen(9000)app.get('/api/users', (req: Request & { html: string }, res: Response) => {// html属性它是我们自定义提供 是开发者自己创建的req.html = 'abc'res.send('aaa')
})

3.15 类型断言

**断言:**断定某一个类型或值。有些情况下,变量的类型对于我们来说是很明确,但是TS编译器却并不清楚,此时,可以通过类型断言来告诉编译器变量的类型。

语法:[值 as 类型] 或 [<类>值]

类型断言:

假设现在有一个 arg 变量,它既可能是 number 类型也可能是 string 类型,当我们访问它的 length 属性时,就会报错,原因是,arg 如果为 number 类型的话,就没有 length 属性。想要解决这一问题,我们有两种方法:

  1. 类型保护

    function fn(arg: number | string) {// string类型上面是有length属性,但是number它没有,所以你直接用,它就会报错,number也是有可能的// 类型保护if (typeof arg === 'string') return arg.lengthreturn arg
    }
    
  2. 断言

    function fn(arg: number | string) {// string类型上面是有length属性,但是number它没有,所以你直接用,它就会报错,number也是有可能的// 断言它现在一定是一个string类型的变量// return (<string>arg).lengthreturn (arg as string).length
    }
    

值断言:

值断言指用符号!:表示当前变量一定会有值,不会为空。

class Person {// 属性暂时可能没有赋值,但是后续我一定会赋值给它,所以可以用一个断言  非空name!: string// 也可以在构造函数中赋值// constructor(name: string) {//   this.name = name// }
}

链判断符:

判断?.左侧对象是否为 null 或 undefined ,如果是就返回 undefined。

res?.data相当于:res == null ? undefined : res.data

在这里插入图片描述


http://www.ppmy.cn/news/142821.html

相关文章

TS的介绍

1.什么是ts ts可以理解为JavaScript的超集&#xff0c;它是由微软公司开发的一种编程语言&#xff0c;可以运行在任何浏览器还有操作系统 2.全局安装ts npm i -g typescript 3.ts的优点 1&#xff09;灵活&#xff1a;可以将代码自动转换为js代码 2&#xff09;兼容性强&a…

远程连接相关操作技巧

作在工作中&#xff0c;经常需要远程连接到服务器上&#xff0c;然而在公司里&#xff0c;老总、同事都需要连接到服务器上的&#xff0c;而默认的Win2003操作系统最大连接数是2&#xff0c;这样一来&#xff0c;问题也就来了&#xff0c;常常遇到“终端服务器超出最大连接数”…

spring-boot版本影响Spring AOP @Before @Around @After等执行顺序

郁闷了半天&#xff0c;我通过AOP切面打印的日志顺序怪怪的&#xff0c;网上查了好几篇文章都说没问题&#xff0c;最后发现是springboot版本升级后Before Around After等执行顺序发生了变化。 1.切面类 Aspect// 这是一个切面 Component// 这是一个需要被装配的spring bean S…

基于Jackson实现API接口数据脱敏

一、背景 用户的一些敏感数据&#xff0c;例如手机号、邮箱、身份证等信息&#xff0c;在数据库以明文存储&#xff08;加密存储见《基于Mybatis-Plus拦截器实现MySQL数据加解密》&#xff09;&#xff0c; 但在接口返回数据给浏览器&#xff08;或三方客户端&#xff09;时&a…

ORA-39001

oracle 11g执行expdp导出脚本时报错&#xff1a; ORA-39001:参数值无效 ORA-39000:转储文件说明错误 ORA-31641:无法创建转储文件“xxxxx.dmp" ORA-27038:所创建的文件已存在 OSD-04010&#xff1a;?????<create>??,?????????? 解决方式&#xf…

ORA-39002 ORA-39168

impdp导入报错ORA-39002 ORA-39168 $ impdp \/ as sysdba\ parfileimpdp.par Import: Release 11.2.0.4.0 - Production on Fri Apr 16 10:57:13 2021Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.Connected to: Oracle Database 11g Ente…

VS-RK3399性能介绍

VS-RK3399采用6核64位处理器&#xff0c;主频1.8Ghz。GPU采用Mali-T860 GPU, OpenGL ES1.1/2.0/3.0/3.1, OpenVG1.1, OpenCL,DX11等规范。 搭载嵌入式Android 7.1版本系统,板载DDR3 2GB内存, 并可支持3G/4G通信模块扩展&#xff0c;HDMIEDPMIPI显示输出(支持1080P) 板载16GB NA…

DFB激光器电流温度与波长的关系

电流增加&#xff0c;波长增加&#xff0c;温度电压增加&#xff0c;温度降低&#xff0c;波长减小 图里面是温度的电压&#xff0c;不是温度&#xff0c;所以随着温度电压&#xff08;热敏电阻电压&#xff09;的增大&#xff0c;温度降低&#xff0c;波长减小 DFB激光器-北京…