javascript的数据类型我们都知道, TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。
1、Typescript的原始数据类型
- 布尔类型(boolean)
let isBool: boolean = false
//或者
let isBool: boolean = true
// 如果你写成其他类型的值,就会提示报错
let isBool: boolean = 'string'
- 数值(number)
let age:number = 23
// 支持二进制
let binaryNumbe:number = 0b1111
- 字符串(string)
let userName:string = '张三'
// 支持模板字符串
let moduleString:string = `${userName}已经${age}岁啦,哈哈哈哈`
- undefined
let un:undefined = undefined
// undefined是所有类型的子集
let count:number = undefined
- null
let nu:null = null
2、any类型 和联合类型
(1)、any类型
any允许赋值为任意类型,如果知道变量的类型,避免使用any,这样子就失去了类型检查的作用了。使用环境:在不知道会输入什么类型的情况下使用
//可以是boolean
let anyThing:any = true
// 数值
anyThing = 123
// 字符串
anyThing = '复制给字符串'
// 还可以是属性
anyThing.hahha
// 还可以是方法
anyThing.getName()
(2)、联合类型
联合类型就是只允许一部分的类型匹配,比如一个变量,我们只允许是string类型和number类型的值,写法如下
let StringOrNumber:string | number = '我是字符串'
//或者
let StringOrNumber:string | number = 123
3、Array和Tuple
(1)、Array类型
// 表示这个数组的项都是数值类型的
let list:number[] = [1,2,3,4,5]
(2)、Tuple(元祖类型):一个已知元素数量和元素类型的数组,每项的类型可以不相同,例如一个数组,一共两项,第一项为string类型的,第二项为数值类型的
let list:[string,number] = ['hello',123]
假如我想给list数组添加一项内容的话,这个值也必须是string,number的其中一种类型才可以,使用联合类型代替,代码:
list[3] = 'hello'
// 或
list[3] =123
// 如果给一个不是这两个类型的就会报错
list[3] = true //报错
4、接口(Interface)
- 对对象的形状进行描述(属性或方法)
- 对类(class)进行抽象
(1):简单用法
interface Person {
name:string,
age:Number
}
let test:Person = {
name:'lili',
age:20
}
以上test如果多加一个属性或少加一个属性都会报错,那么我们如果只想要其中一个属性,比如age是可选的,怎么办呢,代码如下:
interface Person {
name:string,
age?:Number
}
let test:Person = {
name:'lili'
}
如果某个属性只读的话,我们使用readonly的关键字,写法如下:
interface Person {
readonly id:number,
name:string,
age?:number
}
let test:Person = {
id:123,
name:'lili'
}
//改变id的值,就会报错
test.id = 111 //报错
5、函数和类型推断
- 函数 ,对函数的传进来的参数和函数返回值进行类型定义
1:函数声明写法如下:
function sumTotal (x:number,y:number):number {
return x+y
}
let result = sumTotal(1,2)
如果参数是可传可不传的话,也可用?来定义,注意可选参数的话,一定到放在最后面写,代码如下:
function sumTotal (x:number,y:number,z?:number):number {
if(typeof z === 'number'){
return x+y+z
}else {
return x+y
}
}
let result = sumTotal(1,2,3)
还可以给参数定义默认值,代码如下:
function sumTotal (x:number,y:number,z:number = 10):number {
if(typeof z === 'number'){
return x+y+z
}else {
return x+y
}
}
let result = sumTotal(1,2,3)
2:函数表达式,那么定义的变量也是一个函数类型的变量,代码如下
let sumTotal = function (x:number,y:number,z:number = 10):number {
if(typeof z === 'number'){
return x+y+z
}else {
return x+y
}
}
如果我们将sumTotal赋值给一个变量,不能将变量的类型定义成number,string这些,要不然会报错,我们应该定义成一个sumTotal 相同类型的,代码如下
let sumTotal2:(x:number,y:number,z:number)=>number = sumTotal
以上的箭头不是箭头函数,是ts特有的,指的是函数返回的类型
- 类型推断:但是如果我们这样子写:let sumTotal3 = sumTotal ,代码也不会报错,因为typescript在没有明确指定类型的时候会进行推断类型。
6、类(Class)
- 类(class):定义了一切事物的抽象特别,包括属性和方法
- 对象(Object):类的实例
- 面向对象的三大特性:封装、继承、多态
(1):首先先复习一下类和面向对象的基础知识
class Animal {
name:string;
constructor(name:string) {
this.name = name
}
run(){
return `${this.name} 在跑步~`
}
}
实例:
const dog = new Animal('小黑')
dog.run() // 小黑在跑步
继承:
class Cat extends Animal {
eat(){
return `${this.name} 在吃饭饭`
}
}
let miao = new Cat('小花')
miao.run() // 小花在跑步~
miao.eat() // 小花在吃饭饭
方法重写:
class Dog extends Animal {
constructor(name:string){
super(name)
}
run(){
return '看~' +`${this.name}在跑步`
}
}
let xiaobai = new Dog('小白')
xiaobai.run() // 看~小白在跑步
(2):修饰符:
- public:所修饰的属性和方法是公有的,可以在任何地方访问的到,默认不写的都是public
class Animal {
public name:string;
constructor(name:string) {
this.name = name
}
run(){
return `${this.name} 在跑步~`
}
}
// 实例
const dog = new Animal('小黑')
dog.name // 小黑
- private :私有的,被这个修饰的属性和方法只能在这个类里面进行访问,子类也不能访问
class Animal {
private name:string;
constructor(name:string) {
this.name = name
}
run(){
return `${this.name} 在跑步~`
}
}
// 实例
const dog = new Animal('小黑')
dog.name // 报错
- protected :子类可以进行访问
class Animal {
protected name:string;
constructor(name:string) {
this.name = name
}
run(){
return `${this.name} 在跑步~`
}
}
class Cat extends Animal {
eat(){
return `${this.name} 在吃饭饭`
}
}
- readonly:修饰的方法和属性只能读不能写
class Animal {
readonly name:string;
constructor(name:string) {
this.name = name
}
run(){
return `${this.name} 在跑步~`
}
}
const dog = new Animal('小黑')
dog.run() // 小黑在跑步
dog.name
dog.name = 'hahh ' // 报错
- static:被修饰的属性和方法不需要实例也可以直接访问,当类中的定义和实例没有太大关系的时候可以使用静态修饰符
class Animal {
name:string;
static listAnimal:string[] = ['狗','猫','猪']
constructor(name:string) {
this.name = name
}
run(){
return `${this.name} 在跑步~`
}
static isAnimal(a){
return a instanceof Animal
}
}
console.log(Animal.listAnimal)
// 实例
const dog = new Animal('小黑')
Animal.isAnimal(dog) // true
7、类和接口
当两个不同的类,他们都有相同的一个方法的时候,我们可以使用Interface和implements相结合来实现,列如手机和汽车都有导航的功能,但是他们属于同一个父类,代码如下:
//创建一个接口
interface Test {
navigation():void
}
// 创建一个汽车类 使用Test的方法
class Car implements Test {
navigation(){}
}
// 创建一个手机类 使用Test的方法
class Phone implements Test {
navigation(){}
}
再比如手机还有一个特别的功能,视频 ,那我们还可以这样子写:
interface Video{
video():void
}
class Phone implements Test,Video {
navigation(){}
video(){}
}
8、枚举(Enum)
- 定义一些取值范围在一定范围内的常量,例如 一周的时间固定7天,或者方向东南西北等
// 枚举
enum Direction {
East,
West,
South,
North
}
console.log(Direction.East) // 0
console.log(Direction[0]) // East
它可以看做是一个数组,可通过数组的写法获取值,同时也可以枚举成字符串,代码如下
enum Direction {
East = 'East',
West = 'West',
South = 'South',
North = 'North'
}
console.log(Direction.East) // East
我们还可以使用常量枚举,常量枚举可以提升性能,原因是编译过后的文件,代码少了,没有那么多的代码
cosnt enum Direction {
East = 'East',
West = 'West',
South = 'South',
North = 'North'
}
9、泛型(Generics)
- 定义函数、接口或类的时候,不预先指定具体类型,而是在使用的时候再指定类型的一种特征。
- 常用写法
function echo <T>(arg:T):T {
return arg
}
const result = echo('str')
const result1 = echo(123)
const result2 = echo(true)
传两个参数:
function swap<T,U>(tuple:[T,U]):[U,T] {
return [tuple[1],tuple[0]]
}
const result5 = swap(['string',123])
console.log(result5) // [123,'string']
10、约束泛型
如果我想在函数中使用某个属性,但是我不知道传入的参数是不是有这个属性,我写上这个属性的话,就会报错,这时候我们就可以使用接口来约束泛型
interface IWithLength {
length:number
}
function echoWithLenth<T extends IWithLength>(arg:T):T {
console.log(arg.length)
return arg
}
const str = echoWithLenth('str')
const arr = echoWithLenth([1,2,3])
const obj = echoWithLenth({length:10,name:'hahha'})
11、在类和接口中使用泛型
- 在类中使用泛型
class Queue<T> {
private data = [];
push (item:T) {
return this.data.push(item)
}
pop():T{
return this.data.shift()
}
}
const queue = new Queue<number>()
queue.push(1)
queue.pop().toFixed()
const queue2 = new Queue<string>()
queue2.push('str')
queue2.pop().length
- 在接口中使用泛型
interface KeyPair<T,U> {
key:T,
value:U
}
let kp1:KeyPair<string,number> = {key:'str',value:123}
let kp2:KeyPair<number,string> = {key:123,value:'123'}
- 函数中使用泛型
interface IPlus<T> {
(a:T,b:T):T
}
function plus(a:number,b:number):number{
return a+b
}
function connect(a:string,b:string):string{
return a+b
}
const a:IPlus<number> = plus
const b:IPlus<string> = connect
12、类型别名
在要定义类型比较多的时候,我们写一长串可费事啦,用类型别名可就省事多啦,看起来不会很长一个
例如下面这段代码,可以这么写,哈哈哈~
function plus(a:number,b:number):number{
return a+b
}
const a:(a:number,b:number)=>number = plus
可以改写成
type plusType = (a:number,b:number)=>number
function plus(a:number,b:number):number{
return a+b
}
const a: plusType = plus