一、TypeScript简介
TypeScript
是微软开发,是基于JavaScript
的一个扩展语言TypeScript
包含了JavaScript
的所有内容,即:TypeScript
是JavaScript
的超级TypeScript
增加了:静态类型检查、接口、泛型等很多现代开发特性,因此更适合大型项目的开发TypeScript
需要编译为JavaScript
,然后交给浏览器或其他JavaScript
运行环境执行
二、TypeScript编译
自动化编译
1.创建TypeScript
编译控制文件(tsconfig.json
)
tsc --init
//注:安装TypeScript编译器
npm i typescript -g
2.监视目录中的.ts
文件变化(实时编译)
tsc --watch
优化:设置当编译出错时不生成.js
文件
//tsconfig.json的70行,注释解开即可
"noEmitOnError": true
注:后续如果用框架(Vue等),会基于脚手架(vite等),进行自动编译(上述了解即可)
三、类型声明
//1.定义变量a,为string类型
let a: string
//2.定义函数形参为string类型,返回值为number类型
function demo(x:string,y:string):number{}
四、类型推断
//这样定义,ts会自动把它转成string类型,后续不能瞎赋值
let a = 'abc'
//等同于
let a: string = 'abc'
五、类型总览
JavaScript中的数据类型
- string
- number
- boolean
- null
- undefined
- bigint
- symbol
- object
注:其中object包含:Array、Function、Date、Error等。
TypeScript中的数据类型
-
上述所有JavaScript类型都有
-
六个新类型:
- any
- unknown
- never
- void
- tuple
- enum
-
两个用于自定义类型的方式:
- type
- interface
注意:小写string和大写String不一样。(其它的也都不一样)
- string:这是基本数据类型,不能存包装类(new String())
- String:这是包装类,是object类型
六、常用类型
1、Any
定义:任意类型,一旦变量类型为any,就意味着放弃了对该对象的类型检查。
//这就跟js一样了
let a: any
a = 100
a = '你好'
a = false
//这样定义any也行
let b
b = 100
b = '你好'
b = false
//注意:any类型的变量,可以赋值给任意类型的变量
let c: any
c = 9
let x: string
x = c // 无警告
2、unknown
定义:未知类型
1.unknown可理解为一个类型安全的any。适用于:不确定具体数据类型时。
let a: unknown
a = 100
a = false
a = '你好'
let x: string
x = a //警告:不能将“unknown”分配给类型“string”
2.unknown会强制开发者在使用之前进行类型检查,从而提供更强的类型安全性。
let a: unknown
a = 'hello'
//1.加类型判断
if(typeof a == 'string'){
x = a
console.log(x)
}
//2.加断言(两种方式)
x = a as string
x = <string>a
3.读取any类型的任意属性都不会报错,而unknown正好相反。
let str1: string
str1 = 'hello'
str1.toUpperCase() //无警告
let str2: any
str2 = 'hello'
str2.toUpperCase() //无警告
let str3: unknown
str3 = 'hello'
str3.toUpperCase() //警告:“str3”的类型为“未知”
//使用断言强制指定str3的类型为string
(str3 as string).toUpperCase() //无警告
3、never
定义:任何值都不是,就是不能有值。
1.几何不用never去直接限制变量,因为没意义
let a: never
// 以下的所有赋值都会报错
a = 1
a = true
a = undefined
a = null
2.never也可用于限制函数的返回值
//一般返回值为never,则程序必须不能执行完
function throwError(): never{
throw new Error('程序异常退出')
}
//可以写一个无线循环的递归调用
function a(): never{
a()
}
//这样也会报错,因为会返回undefined
function a(): never{
}
3.never一般是TypeScript主动推断出来的
let a: string
a = 'hello'
if (typeof a === 'string') {
console.log(a.toUpperCase())
} else {
console.log(a) //ts会推断此处的a是never,因为程序永远不会走这里
}
4、void
作用:一般用于函数返回值声明。
含义:函数不返回任何值,调用者也不应依赖其返回值进行任何操作
function logMessage(msg: string): void{
console.log(msg)
}
logMessage('你好')
//注意:logMessage函数没写return指定返回值,所有该函数是没有显示返回值的,但会有一个隐式返回值undefined;
理解void 与 undefined
- void是一个广泛的概念,用来表达“空”,而undefined则是这种“空”的具体实现。
- 因此undefined是void能接受的“空”状态的一种具体形式。
总结:若函数返回类型为void,那么:
1.从语法上讲:函数是可以返回undefined的,至于显示,还是隐式返回,这无所谓!
2.从语义上讲:函数调用者不应关心函数返回的值,也不应依赖返回值进行任何操作!即使返回了undefined值。
5、object
关于object与Object,结论:实际开发中用的相对较少,因为范围太大
1.object(小写)
let a: object //a的值可以是任何【非原始类型】
//这些就是【非原始类型】,其实就是Java中的引用数据类型
a = {}
a = {name:'张三'}
a = function(){}
a = new String('123')
class Person {}
a = new Person()
// 以下代码均为【原始类型】,会报错
a = 1
a = true
a = '你好'
a = null
a = undefined
2.Object(大写)
let b: object //b的值必须是Object的实例对象
//可以调Object的方法的都可以
b = {}
b = {name:'张三'}
b = function(){}
b = new String('123')
class Person {}
b = new Person()
b = 1
b = true
b = '你好'
// 以下会有警告
b = null
b = undefined
3.声明对象类型
//?表示可选参数,中间可以用【逗号,分号,换行】做分隔
let person: {name: string, age?: number}
person = {name: '张三',age: 18}
person = {name: '李四'}
//索引签名:允许对象有任意数量的属性,这些属性的键和类型都是可变的
let person: {
name: string
age?: number
[key: string]: any //索引签名,可以不用key这个单词,换成其他的也行
}
person = {
name: '张三',
age: 18,
gender:'男',
... //还可以写多个只有满足类型为any
}
4.声明函数类型
//这里的=>表示函数返回值类型
let count: (a: number, b: number) => number
//这里的函数形参名可以不一致
count = function (x,y){
return x + y
}
5.声明数组类型
let arr1: string[]
let arr2: Array<string> //这里必须写泛型
arr1 = ['a','b','c']
arr2 = ['hello','world']
6、tuple
定义:是一种特殊的数组类型,可以存储固定数量的元素,并且每个元素的类型是已知的且可以不同。元组用于精确描述一组值的类型,
?
表示可选元素
let arr1: [string,number]
let arr2: [number,boolean?] //?表示可选
let arr3: [number,...string[]] //这里的string表示可变参数,可写任意个
arr1 = ['hello',123]
arr2 = [100]
arr3 = [200,'a','b']
7、enum
定义:可以定义一组命名常量,它能增强代码的可读性,也让代码更好维护。
1.数字枚举
// 定义一个描述【上下左右】方向的枚举Direction
enum Direction {
Up,
Down,
Left,
Right = 6 //可以自己设置下标,后面的依次递增
}
//反向映射
console.log(Direction.Up)
console.log(Direction[0]) //可以通过下标访问
2.字符串枚举
enum Direction {
Up = 'up',
Down = 'down',
Left = 'left',
Right = 'right'
}
let dir: Direction = Direction.Up;
console.log(dir) //输出:"up"
3.常量枚举
官方描述:是一种特殊枚举类型,它使用
const
关键字定义,在编译时会被内联,避免生成额外的代码。
//const相当于把此枚举只定义在ts中,而不编译到js中
[const] enum Direction {
Up,
Down,
Left,
Right
}
console.log(Direction.Up)
//不加const生成的js代码
var Direction;
(function (Direction) {
Direction[Direction["Up"] = 0] = "Up";
Direction[Direction["Down"] = 1] = "Down";
Direction[Direction["Left"] = 2] = "Left";
Direction[Direction["Right"] = 3] = "Right";
})(Direction || (Direction = {}));
console.log(Direction.Up);
//加了const生成的js代码
console.log(0 /* Direction.Up */);
七、自定义类型
type
可以为任意类型创建别名,让代码更简洁、可读性更强,同时能更方便地进行类型复用和扩展。
1.联合类型
//定义Status类型,可以是number或string
type Status = number | string
function printStatus(status: Status){
console.log(status)
}
printStatus(404)
printStatus('200')
2.交叉类型
//面积
type Area = {
height: number; //高
width: number; //宽
}
//地址
type Address = {
num: number; //楼号
cell: number; //单元号
room: string; //房间号
}
//定义House联合类型,必须有Area和Address的所有属性
type House = Area & Address;
const house: House = {
height: 180, //高
width: 75, //宽
num: 6, //楼号
cell: 3, //单元号
room: 702, //房间号
}
一个特殊情况:
使用类型申明限制函数返回值为void是,ts并不会严格要求函数返回空。
type LogFunc = () => void
const f1: LogFunc = () => {
return 100; //允许返回非空值
}
const f2: LogFunc = () => 200;//允许返回非空值
const f3: LogFunc = function () {
return 300; //允许返回非空值
}