TypeScript常用类型
TS中常用基础类型细分为 1.JS已有类型;2.TS新增类型
JS已有类型
- 原始类型:number/string/boolean/null/undefined/symbol
- 对象类型:object(包括数组、对象、函数等)
TS新增类型
联合类型、自定义类型(类型别名)、接口、元组、字面量类型、枚举、void、any等
TypeScript 类型运用
原始类型
let age : number = 18
let name: string = '小明'
对象类型
对象类型
- 对象的类型就是在描述对象的结构(有什么类型的属性和方法)
//属性类型之间用 ; 分隔
let person = {name: string; age: number; sayHi(tip: string): void} = {
name : 'jay',
age : 18,
sayHi(tip){}
}
//可以用换行来去掉 ; 分隔
let person = {
name: string
age: number
sayHi: (tip: string) => void //也可以用箭头函数
} = {
name : 'jay',
age : 18,
sayHi(tip){}
}
- 对象可选属性
function myAxios(config: {url: string; method? :string }) {
console.log(config)
}
myAxios({
url: ''
})
myAxios({
url: '',
method : ''
})
数组
let numbers : number[] = [1,2,3]
let strings : string[] = ['1','2','3']
let arr : (number|string)[] = [1,2,'3','4']
函数类型
函数的类型实际上指的是:函数的参数和返回值的类型
- 单独指定参数和返回值的数据类型
function Fun1(num1 : number,num2 : number) : number {
return num1 + num2
}
const Fun1 = (num1 : number,num2 : number) : number => {
return num1 + num2
}
- 同时指定参数和返回值的数据类型
const Fun1 : (num1 : number,num2 : number) => number = (num1,num2) => {
return num1 + num2
}
- 函数没有返回值,用void
function Fun1(num1 : number,num2 : number) : void {
console.log( num1 + num2 )
}
- 函数的参数可选 可选参数:在可传可不传的参数名称后面添加 ?(问号)
注:可选参数只能出现在参数列表的最后,也就是说可选参数后面不能再出现必选参数
function Fun1(num1 : number,num2? : number) : void {
console.log( num1 + num2 )
}
Fun1(1)
Fun1(1,2)
联合类型
定义:由两个或多个其他类型组成的类型,表示可以是这些类型中的任意一种(注:中间用 | 隔开)
let arr : (number|string)[] = [1,2,'3','4']
let arr : number |string[] = 1 //注意,有无()
自定义类型(类型别名)
用type关键字自定义一种类型,可以多次被使用,简化类型的使用
type customarrary = (number|string)[]
let arr1 : customarrary = [1,'2',3]
let arr2 : customarrary = ['1','2',3]
接口(interface)
定义:当一个对象类型被多次使用时,一般会使用 接口(interface) 来描述对象的类型,达到复用的目的
interface CustomPerson {
name : string
age : number
sayHi() : void
}
let person1 : CustomPerson = {
name : 'person1',
age : 18,
sayHi('你好'){}
}
let person2 : CustomPerson = {
name : 'person2',
age : 20,
sayHi('你好2){}
}
接口继承(extends)
如果两个接口之间有相同的属性或方法,可以将公共的属性或方法抽离出来,通过继承来实现复用
interface Point1 {
x : number
y : number
}
interface Ponit2 {
x : number
y : number
z : number
}
//用继承
interface Point1 {
x : number
y : number
}
interface Ponit2 extends Point1 {z : number} // Ponit2继承了Ponit1的所有属性和方法,且拥有z属性
类型别名(type)和 接口(interface)的对比
- 相同点: 都可以为对象指定类型
- 不同点:
- 接口,只能为对象指定类型
- 类型别名,不仅可以为对象指定类型,还可以为任意类型指定别名
- 类型别名的声明方式是赋值,用=
- 接口的声明方式直接跟 {}
元组(Tuple)
定义: 是另一种类型的数组,它可以确切地知道包含多少个元素,以及特定索引对应的类型。
//例如表示确切经纬度
let position : [number, number] = [39.5427, 116.2317]
类型断言(as)
使用 as 关键字,后面跟一个更加具体的类型,使变量类型变得更加具体
const alink = document.getElementById('link') as HTMLAnchorElement
技巧:在浏览器控制台,通过console.dir()打印DOM元素,在属性列表的最后面,即可看到该元素的类型。
字面量类型
使用模式:字面量类型配合联合类型一起使用。
使用场景:用来表示一组明确的可选值列表。
优势: 相比于string类型,使用字面量类型更加精确、严谨。
function changeDirection( direction: 'up'|'down'|'left'|'right' ) {
console.log(direction)
}
枚举类型(enum)
定义: 定义一组命名常量。枚举不仅用作类型,还提供值(枚举成员都是有值的)
使用规范: 约定枚举名称、枚举中的值以大写字母开头,用 ,(逗号)分隔
引用枚举: 直接通过点(.)语法访问枚举成员
enum Direction { Up, Down, Left, Right }
function changeDirection( direction: Direction ) {}
changeDirection( Direction.Up )
数字枚举:枚举成员为数字的枚举
注意: 枚举成员是有值的,默认为: 从0开始自增的数值
// Up=0;Down=1;Left=2;Right=3;
enum Direction { Up, Down, Left, Right }
// Down=11;Left=12;Right=13;
enum Direction { Up=10, Down, Left, Right }
// Right=17;
enum Direction { Up=10, Down=14, Left=16, Right }
字符串枚举:枚举成员为字符串的枚举
注意: 字符串枚举没有自增长行为,字符串枚举的每个成员必须有初始值
enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
TS中的typeof运算符
- TS中的typeof与JS中的typeof是不一样的
- TS中的typeof可以用来获取上下文中的变量类型
let p={ x: 1,y: 2 }
let a = typeof p.x //number
- TS中的typeof只能用来查询变量或属性的类型,无法查询其他形式的类型(比如:函数调用的类型)
TypeScript 高级类型
TS中的高级类型有:class类、类型兼容性、交叉类型、泛型和keyof、索引签名类型和索引查询类型、映射类型
class类
class Person {
age : number
gender = '男'
}
const p = new Person() //创建一个实例
p.age
p.gender
构造函数(注:构造函数无返回值)
class Person {
age : number
gender = '男'
// 构造函数
constructor(age: number, gender: string) {
this.age = age
this.gender = gender
}
}
const p = new Person(18,'男') //创建一个实例
p.age
p.gender
类的实例方法
class Ponit {
x = 1
y = 2
//实例方法
scale(n: number): void {
this.x *= n
this.y *= n
}
}
const p = new Ponit()
p.scale(2)
console.log(p.x,p.y) // x=2,y=4
类的继承
类的继承有两种方式:1.extends(继承父类);2.implements(实现接口)
- extends(继承父类)
class A {
move () {console.log('a')}
}
// B继承了A,也拥有了A.move()
class B extends A {
bark() {console.log('b')}
}
const b = new B()
b.move()
b.bark()
- implements(实现接口)
interface A {
sing(): void
name: string
}
// B类实现接口A意味着:B类中必须要提供接口A中指定的所有方法和属性
class B implements A {
name: 'b'
sing() {
console.log('a')
}
}
类成员可见性
类里面的属性和方法对外部分可见
可见性修饰符:
- public(公有的),默认的,可省略。
- protected(受保护的),仅对其声明所在类和子类中(非实例对象)可见。
class A {
// 受保护的方法
protected move () {console.log('a')}
sing() {
this.move() //可调用
}
}
// B继承了A,也拥有了A.move()
class B extends A {
bark() {console.log('b')}
this.move() //可调用
}
const b = new B()
b.move() //不可调用
- private(私有的),只在当前类中可见,对实例对象以及子类均不可见。
- readonly(只读),表示只读,用来防止在构造函数之外对属性进行赋值。
//类
class Person {
readonly age: number =18
constructor(age: number) {
this.age = age
}
}
//接口
interface A {
readonly name: string
}
//对象类型
let obj = { readonly name: string} = {
name = 'a'
}
注:
- 属性age后面的类型注解(比如:此处的number)如果不加,则age的类型为18(字面量类型)。
- readonly修饰符修饰的类型必须要有明确的类型注解。
- readonly只修饰属性,不修饰方法。
- readonly可以修饰接口或者{}表示的对象类型。
类型兼容性
TS是结构化类型系统(Structural Type System):类型检查关注的是值所具有的形状。
对象类型的兼容性
注:成员多的赋值给成员少的
class Ponit{x: number; y: number}
class Ponit2D {x: number; y: number}
class Ponit3D {x: number; y: number; z: number}
const Point = new Ponit2D
const Point = new Ponit3D
//错误赋值
const Ponit3D = new Ponit2D
接口的兼容性
接口之间的兼容性和class类似。并且,class 和interface之间也可以兼容
interface Ponit{x: number; y: number}
interface Ponit2D {x: number; y: number}
interface Ponit3D {x: number; y: number; z: number}
let p1: Ponit
let p2: Ponit2D
let p3: Ponit2D
p1= p2
p1= p3
//错误赋值
// p3 = p1
//接口与类class之间也可以兼容
class Point4D{x: number; y: number; z: number}
p1 = new Point4D()
函数的兼容性
函数的兼容性比较复杂,需要考虑以下几个因素:
- 参数的个数 (参数少的可以赋值给参数多的,与对象和接口相反)
- 参数的类型
- 返回值类型
type F1 = (a: number)=> void
type F2 = (a: number, b: number)=> void
let f1: F1
let f2: F2
f2 = f1
// 错误示范
// f1 = f2