TypeScript

TypeScript是JavaScript的超集,引入了类型检测以提升开发体验。它允许在编译阶段捕获错误,支持多种数据类型如number、string、boolean、null、undefined等。文章介绍了如何设置编译环境,变量声明,以及对象、数组、函数等类型的详细用法,还包括元组、枚举、联合类型、接口和类型断言等概念,帮助开发者更好地理解和使用TypeScript。
摘要由CSDN通过智能技术生成

认识TS

  • JavaScript没有加入类型检测这一机制
  • 2014年Microsoft微软 推出了TypeScript1.0版本
  • TypeScript 是拥有 类型 的 JavaScript超集
  • 错误提示越早越好
  • 编写代码(IDE)>>> 代码编译(TS)>>> 代码运行 (浏览器)
  • TypeScript最终会被编译成JavaScript代码,所以你并不需要担心它的兼容性问题,在编译时也可以不借助于Babel这样的工具
  • 明确限制 数据类型 和 个数

TypeScript的编译环境

全局安装

  • 前提保证有node环境
	npm install typescript -g
  • 查看版本
	tsc --version

编译

tsc编译

//进入目录
	tsc index.ts
//浏览器或者Node环境下运行JavaScript代码
	node index.js

webpack

配置本地的TypeScript编译环境和开启一个本地服务,可以直接运行在浏览器上

ts-node 库

// 安装 ts-node
	npm install ts-node -g
//另外ts-node需要依赖 tslib 和 @types/node 两个包
	npm install tslib @types/node -g
	ts-node index.ts

Ts变量的声明

  • var/let/const 标识符: 数据类型 = 赋值;
  • 不推荐用var ,没有块级作用域
  • 首次赋值时的 数据类型 不可再变

类型推论

  • 第一次声明一个标识符时,如果直接赋值(省略数据类型),会根据所赋值的类型 推论 出标识符的类型注解 (鼠标悬浮显示),这个过程就 是 类型推论
  • let 类型推论, 推论出的是 通用类型
  • const类型推论,推论出的是 字面量类型

注意

  • ts环境不管 多少个编译都是全局的
  • 需要给每个ts文件都添加一个 export {} ,防止标识符(变量)冲突

Ts中的数据类型

number 数值型

  • TypeScript和JavaScript一样,不区分整数类型(int)和浮点型(double)
  • 双精度 64 位浮点值
  • 支持二进制、八进制、十六进制
	num = 100;		//十进制
	num = 0b110;	//二进制
	num = 0o555;	//八进制
	num = 0xf23;	//十六进制

boolean 布尔型

  • true 和 false
  • 表达式

string 字符串类型

  • string s 是小写
  • 使用单引号(’)或双引号(")来表示字符串类型
  • 注意 JAVA 等强类型语言 用的是 双引号 (")
  • 模板字符串

undefined 未定义类型

  • 未定义的值
let u:undefined = undefined 

null 空类型

  • 已定义且值为空
let n:null = null 

Array 数组类型

  1. 元素类型 []
let arr: number[] = [1, 2, 3];
const arr2: string[] = ["aaa","bbb","ccc"];
let arr: ( number | string | number[] )[] = [1, '4', [1, 2, 4]]
  1. 数组泛型
let list: Array<number> = [1, 2, 3];
let list: Array<string> = ["aaa","bbb","ccc"];

Object 对象类型

  • object表示非原始类型,也就是除numberstringbooleansymbolnullundefined之外的类型
  • json对象,函数,数组均可以
let obj: object = {
    name: 'tom'
}
//object是通用类型,找不到里边的属性
console.log(obj.name) //报错
//但实际不会这么用
let obj={}=[]
  • 严格限制对象结构,对象的每一个属性都需要数据类型约束
        let loginParams: {
            userName: string,
            userPass: string
        };
        loginParams = {
            userName: "张三",
            userPass: "1234"
        };
        let loginParams: {
            userName: string,
            userPass: string
        } = {
            userName: "张三",
            userPass: 1234,  //报错
            age: 12		//报错
        }
  • 如果某一个属性是可有可无的,可以设置一个 ?
let user: { name: string, age: number, gender?: string } = {
    name: '张三',
    age: 20
}

Symbol 类型

在这里插入图片描述

函数 类型

  • 限制函数的参数类型 及 返回值,返回值没限制 会推论
function sum(num1: number, num2: number) {
  return num1 + num2
}
等同于
function sum(num1: number, num2: number):number {
  return num1 + num2
}

const res = sum(123, 321)
  • (上下文类型)大多数 匿名函数 会根据上下文 推论 类型,不需要添加 类型注解
const names: string[] = ["abc", "cba", "nba"]
//function匿名函数 会根据上下文 推论 类型
names.forEach(function(item, index, arr) {
  console.log(item, index, arr)
})
  • 有限个参数无法确定是否会存在 ?
 function fn( a:number, b?:string ){ } 

any 任意类型

  • 无法确定一个变量的类型,并且之后可能会发生一些变化,使用 any
  • any类型的变量进行任何事情都是合法的,包括获取不存在的属性、方法
  • 可以给一个any类型的变量赋值任何的值
  • 相当于关闭了类型检查
   显式:let a:any = "aaa"
   隐式: let a;

unknown 未知类型

  • unknown类型的值上做任何事情都是不合法的,必须进行类型校验(类型缩小)
let a:unknown
let b:string
if(typeof a ==='string'){
    b=a
}

never 从不会出现的值

function parseLyric() {
  return []   //这个数组里边永远不会有内容,  所以类型为 never[]
}
  • 封装工具可能会用到,更加严谨
  • 其他人添加 类型,那么never 就会报错
// 其他时候在扩展工具的时候, 对于一些没有处理的case, 可以直接报错
function handleMessage(message: string | number | boolean) {
  switch (typeof message) {
    case "string":
      console.log(message.length)
      break
    case "number":
      console.log(message)
      break
    case "boolean":
      console.log(Number(message))
      break
    default:
      const check: never = message  //如果上边有一个没有判断的类型,这里就会报错
  }
}

void 类型

  • 表示为空,空也是存在的,这就是和never的区别
  • void通常用来指定一个函数是没有返回值
  • 指定了 void类型,可以 return undefined(Ts编译器允许罢了)
function sum(num1: number, num2: number): void {
	console.log(num1 + num2)
	return undefined
	// return 123 错误的做法
}
  • 应用场景: 用来指定函数类型的返回值是void
// 1.定义要求传入的函数的类型
type ExecFnType = (...args: any[]) => void

// 2.定义一个函数, 并且接收的参数也是一个函数, 而且这个函数的类型必须是ExecFnType
function delayExecFn(fn: ExecFnType) {
  setTimeout(() => {
    fn("why", 18)
  }, 1000);
}
// 3.执行上面函数, 并且传入一个匿名函数
delayExecFn((name, age) => {
  console.log(name, age)
})

  • 基于上下文类型推论的函数中的返回值如果是void类型, 并不会强制函数一定不能返回内容
const names = ["abc", "cba", "nba"]
//没有明确指定为 viod类型,所以可以 return
names.forEach((item: string, index: number, arr: string[]) => {
  console.log(item)
  return 123
})

tuple 元组类型

  • 表示一个已知元素数量和类型的数组,各元素的类型不必相同
  • 例:保存我的个人信息: zhangsan 男 18

/ 1.使用数组类型不合适: 数组中最好存放相同的数据类型, 获取值之后不能明确的知道对应的数据类型
const info1: any[] = ["why", "男", 18]
const value = info1[2]
console.log(value) //类型为any

/2.	使用对象类型(最多)不合适: 会添加多余的key值
const info2 = {
  name: "why",
  sex:"男" ,
  age: 18
}

/ 3.使用元组类型,可以存放不同的数据类型, 取出来的item也是有明确的类型
const info3: [string, string, number] = ["why", "男", 18]
const value2 = info3[2]	//类型为number
  • 在函数中 使用元组类型 ( 函数的多个返回值 )
//指定多个返回值的类型
function useState(initialState: number): [number, (newValue: number) => void] {
  let stateValue = initialState
  function setValue(newValue: number) {
    stateValue = newValue
  }
  return [stateValue, setValue]
}
const [count, setCount] = useState(10)
//如果不指定返回值类型的话,这个函数是 any类型 ,不严谨
setCount(100)

enum 枚举类型

  • 定义数值集合
  • 默认情况下,从0开始为元素编号。 你也可以手动的指定成员的数值
enum Color {Yellow, Red = 1, Green= 5, Blue}
let a: Color = Color[0]; //Yellow
let b: Color = Color[1]; //Red
let c: Color = Color[6]; //Blue

联合类型

  • 满足多个类型中一个即可
  • 使用 | 符号
let appTypeId:string|number=1;
appTypeId="1";
appTypeId=1;

特殊操作

开挂操作,不会报错
let appPlatformId:number=1;
// @ts-ignore
appPlatformId="1";

交叉类型

  • 需要满足多个类型的条件
  • 使用 & 符号
// 交叉类型: 两种(多种)类型要同时满足
type NewType = number & string // 没有意义 never类型

interface IKun {
  name: string
  age: number
}

interface ICoder {
  name: string
  coding: () => void
}

type InfoType = IKun & ICoder

const info: InfoType = {
  name: "why",
  age: 18,
  coding: function() {
    console.log("coding")
  }
}

字面量类型

//将多个字面量类型联合起来 |
type Direction = "left" | "right" | "up" | "down"
const d1: Direction = "left"

// 例子: 封装请求方法,只能有post和get方法
type MethodType = "get" | "post"
function request(url: string, method: MethodType) {}
request("http://codercba.com/api/aaa", "post")

// TS细节
const info = {
  url: "xxxx",
  method: "post"
}
// 下面的做法是错误: info.method获取的是string类型
request(info.url, info.method)

// 解决方案一: info.method进行类型断言
request(info.url, info.method as "post")

// 解决方案二: 直接让info对象类型是一个字面量类型
const info2: { url: string, method: "post" } = {
  url: "xxxx",
  method: "post"
}
// 解决方案三: as const 
const info2 = {
    url: "xxxx",
    method: "post"
} as const
request(info2.url, info2.method)

类型收窄(缩小)

  • Type Narrowing 类型收窄 类型缩小
  • 缩小比声明时更小的类型
  • typeof padding === "number 可以称之为 类型保护(type guards)
  • 常见的类型保护有
    • typeof
function printID(id: number | string) {
  if (typeof id === "string") {
    console.log(id.length, id.split(" "))
  } else {
    console.log(id)
  }
}
  • 平等缩小(比如===, !==, ==, != )
type Direction = "left" | "right" | "up" | "down"
function switchDirection(direction: Direction) {
  if (direction === "left") {
    console.log("左:", "角色向左移动")
  } else if (direction === "right") {
    console.log("右:", "角色向右移动")
  } else if (direction === "up") {
    console.log("上:", "角色向上移动")
  } else if (direction === "down") {
    console.log("下:", "角色向下移动")
  }
}
  • instanceof,检查一个值是否是另一个值的“实例”
//instanceof: 传入一个日期, 打印日期
function printDate(date: string | Date) {
  if (date instanceof Date) {
    console.log(date.getTime())
  } else {
    console.log(date)
  }
//或者  注意Date 判断是Object
  // if (typeof date === "Object") {
  //   console.log(date.getTime())
  // } else {
  //   console.log(date)
  // }
}
  • in操作符,指定的属性在指定的对象或其原型链中,则返回true
    在这里插入图片描述

别名

type 类型别名

  • 所有 数据类型起一个别名,方便复用

type MyNumber = number
const age: MyNumber = 18

type IDType = number | string
function printID(id: IDType) {
  console.log(id)
}

type PointType = { x: number, y: number, z?: number }
function printCoordinate(point: PointType) {
  console.log(point.x, point.y, point.z)
}

interface 接口声明

  • 编译后Js文件中不会体现
  • 只能声明 对象
// 接口: interface
interface PointType2 {
  x: number
  y: number
  z?: number
}

function printCoordinate(point: PointType2) {}
  • interface支持继承的,允许接口继承多个接口
interface IPerson {
  name: string
  age: number
}

interface IKun extends IPerson {
  kouhao: string
}

const ikun1: IKun = {
  kouhao: "你干嘛, 哎呦",
  name: "kobe",
  age: 30
}
  • interface可以被类实现
class Person implements IPerson {

}

区别

  1. type类型使用范围更广,接口类型只能用来声明对象
  2. 在声明对象时,type不允许两个相同名称的别名;interface可以多次声明,最终取合集
type PointType1 = { //报错
    x: number
    y: number
}

type PointType1 = {	//报错
    z?: number
}
interface PointType2 {
  x: number
  y: number
}

interface PointType2 {
  z: number
}

const point: PointType2 = {
  x: 100,
  y: 200,
  z: 300
}
  1. interface支持继承的
  2. interface可以被类实现

类型断言as

  • 允许变量从一种类型更改为另一种类型

  • 例:类不确定绑定在哪,不确定是否有src 和alt 属性,会报错
    在这里插入图片描述

    在这里插入图片描述

  • 使用类型断言as

const imgEl = document.querySelector(".img") as HTMLImageElement
imgEl.src = "xxx"
imgEl.alt = "yyy"
  • TypeScript只允许类型断言转换为 更具体 或者 不太具体 的类型版本,此规则可防止不可能的强制转换
const age3 = age as any
//当你很确定就是字符串类型时
const age4 = age3 as string
console.log(age4.split(" "))

非空类型断言

  • 表示可以确定某个标识符是有值的,跳过ts在编译阶段对它的检测
  • 符号
interface IPerson {
  name: string
  age: number
  friend?: {
    name: string
  }
}

const info: IPerson = {
  name: "why",
  age: 18
}

// 访问属性: 可选链: ?.
console.log(info.friend?.name) //undefined

info.friend?.name = "kobe" //报错

// 解决方案一: 类型缩小
if (info.friend) {
  info.friend.name = "kobe"
}

// 解决方案二: 非空类型断言(有点危险, 只有确保friend一定有值的情况, 才能使用)
info.friend!.name = "james"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值