本文介绍: TypeScript 由微软开发的自由和开源编程语言,它可以在任何任何操作系统运行可以理为TypeScript是JavaScript 的超集,扩展了 JavaScript语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。Ts和Js最大不同,在于Ts类型检查。在一些大型项目,多人合作开发项目中,类型统一一件非常困难的事件,有了Ts加持可以方便类型的统一。


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 src1.ts --outDir dist -w

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

3. ts类型声明

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

注意:

  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

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

3.3 字符串类型

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

// 自动类型赋值
let arg1 = 'hello'

3.4 anyunknown

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

两者区别

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

unknownany安全类型,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 voidnullundefined

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 {
  // 0
  red,
  // 1
  green,
  // 2
  blue,
  // 3
  pink,
  // 4
  yellow
}
// 如果指定的一个变量它的类型为枚举类型,则在赋值时,最好是使用 枚举类型.元素 进行赋值
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 {
  // 0
  red,
  // green
  green = 'green',
  // 10
  blue = 10,
  // 11
  pink,
  // 12
  yellow
}
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 &amp; type2

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

type type1 = { id: number; name: string }
type type2 = { age: number }
// {id:number,name:string,age:number}
type type3 = type1 &amp; 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 &amp; 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 &amp; type2
// let t: type3 = { id: 1, name: 'a', age: 20 } // 报错,id无法来赋值

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

// 假设 Slice 对象是通过npm安装的一个reduxjs中的类型
type Slice = {
  name: string
}

// 通过交叉类型扩展属性
type ExtSlice = Slice &amp; {
  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 &amp; { 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.length
      return arg
    }
    
  2. 断言

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

断言

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

class Person {
  // 属性暂时可能没有赋值,但是后续我一定会赋值给它,所以可以用一个断言  非空
  name!: string

  // 也可以在构造数中赋值
  // constructor(name: string) {
  //   this.name = name
  // }
}

判断符:

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

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

在这里插入图片描述

原文地址:https://blog.csdn.net/weixin_45605541/article/details/128470396

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_33218.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注