1、字面量类型
代码示例:
function changeDirection(direction: 'up' | 'down' | 'left' | 'right') { }
changeDirection('left')
let age: 18 = 18
const str: 'Hello' = 'Hello'
‘Hello'就是一个字面量类型,除字符串外任意的JS字面量(比如对象、数字等)都可以作为类型使用。
使用模式:
字面量类型配合联合类型一起使用
使用场景:
用来表示一组明确的可选值列表
优势:
相比于string类型,使用字面量类型更加精确、严谨。
2、枚举
枚举:定义一组命名常量,枚举的功能类似于字面量类型+联合类型组合的功能,也可以表示一组明确的可选值。
解释:
1、使用enum关键字定义枚举
2、约定枚举名称,枚举中的值以大写字母开头
3、枚举中的多个值通过逗号(,)分隔
4、定义好枚举后,直接使用枚举名称作为类型注解
5、使用时类似于JS中的对象,直接通过点(.)语法访问枚举的成员
代码示例:
enum Direction { Up, Down, Left, Right }
function changeDirection(direction: Direction) { }
changeDirection(Direction.Down)
注意:
1、枚举成员是有值的,默认为:从0开始自增的数值
2、把枚举成员的值为数字的枚举称为数字枚举
3、枚举成员的值都是字符串的枚举称为字符串枚举,需要注意的是字符串枚举没有自增长的行为,因此,字符串枚举的每个成员必须有初始值
4、也可以给枚举中的成员初始化值
代码示例:
enum Direction { Up = 10, Down = 3, Left, Right }
function changeDirection(direction: Direction) { }
changeDirection(Direction.Down)
3、any类型(不推荐使用)
当值的类型为any时,可以对该值进行任意操作,并且不会有代码提示,即使可能存在错误
其他隐式具有any类型的情况:
1、声明变量不提供类型也不提供默认值
2、函数参数不加类型
所以,这两种情况下都应该提供类型
代码示例:
let a
function add(num1, num2) {
return num1+num2
}
4、typeof
在JS中是用来获取数据的类型,TS也提供了typeof操作符:可以在类型上下文中引用变量或属性的类型
解释:
1、typeof出现在类型注解的位置所处的位置就是类型上下文
2、typeof只能用来查询变量或属性的类型,无法查询其他形式的类型
代码示例:
let p = { x: 1, y: 2 }
function formatPoint(point: typeof p) { }
formatPoint({ x: 2, y: 8 })
let num: typeof p.x
5、class类
TS中的class,不仅提供了class的语法功能,也作为一种类型存在
代码示例:
class Person{
age: number
gender = '男'
}
const p = new Person()
p.age
p.gender
构造函数
代码示例:
class Person2 {
age: number
gender: string
constructor(age:number,gender:string) {
this.age = age
this.gender = gender
}
}
const p2 = new Person2(12, '女')
console.log(p2.age,p2.gender);
解释:
1、成员初始化后(比如age: number),才可以通过this.age来访问实例成员
2、需要为构造函数指定类型注解,否则会被隐式判断为any
3、构造函数不需要返回值类型
实例方法
代码示例:
class Point{
x = 1
y = 1
scale(n: number) {
this.x *= n
this.y *= n
}
}
const p3 = new Point()
p3.scale(10)
console.log(p3.x,p3.y);
解释:
方法的类型注解(参数和返回值)与函数用法相同
class类的继承
类继承的两种方式:extends(继承父类)、implements(实现接口)
说明:JS中只有extends,而implements是TS提供的
extends继承代码示例:
class Animal{
move() {
console.log('走两步');
}
}
class Dog extends Animal{
name = '旺旺'
bark() {
console.log('旺旺!');
}
}
const d = new Dog()
d.move()
d.bark()
console.log(d.name);
解释:
1、通过extends关键字实现继承
2、子类继承父类,子类的实例对象就同时具有了父类和子类的所有属性和方法
implements代码示例:
interface Singable{
sing(): void
name: string
}
class Person3 implements Singable{
sing(): void {
console.log('黑色星期五');
}
name = '张三'
}
解释:
1、通过implements关键字让class实现接口
2、Person类实现接口Singable意味着,Person类必须提供Singable接口中指定的所有方法和属性
类成员可见性
可以通过TS来控制class的方法或属性对于class外的代码是否可见
可见性修饰符包括:
public(公有的)、protected(受保护的)、private(私有的)
1、public:公有成员可以被任何地方访问,默认可见,可以直接省略
2、protected:表示受保护的,仅对其声明所在类和子类中(非实例对象)可见,子类的内部可以通过this来访问父类中受保护的成员,但是,对实例不可见
3、private:表示私有的,只在当前类中可见,对实例对象以及子类也是不可见的
public代码示例:
class Animal {
public move() {
console.log('hahahha');
}
}
class Dog extends Animal {
bark() {
console.log('旺旺!');
}
}
const d = new Dog()
d.move
protected代码示例:
class Animal {
protected move() {
console.log('受保护');
}
run() {
this.move
console.log('okk');
}
}
const a = new Animal()
a.run
class Dog extends Animal {
bark() {
console.log('旺旺!');
this.move
}
}
const d = new Dog()
d.run
private代码示例:
class Animal {
private move() {
console.log('私有的');
}
run() {
this.move
}
}
class Dog extends Animal {
bark() {
console.log('旺旺!');
this.run
}
}
const d = new Dog()
readonly只读修饰符
readonly:表示只读,用来防止在构造函数之外对属性进行赋值
解释:
1、使用readonly关键字修饰该属性是只读的,注意只能修饰属性不能修饰方法
2、接口或者{}表示的对象类型,也可以使用readonly
代码示例:
class Person {
readonly age: number = 18
constructor(age: number) {
this.age = age
}
}
interface IPerson{
readonly name: string
}
let obj: IPerson = {
name:'Jack'
}
let obj2: {name: string} = {
name: 'Jack'
}
类型兼容性
两种类型系统:
Structural Type System(结构化类型系统)和Nominal Type System(标明类型系统)
1、TS采用的是结构化类型系统,类型检查关注的是值所具有的形状
2、对于对象类型来说,成员多的可以赋值给少的
3、接口之间的兼容性,类似于class,并且,class和interface之间也可以兼容
代码示例:
class Point { x: number; y: number }
class Point2D { x: number; y: number }
const p: Point = new Point2D()
class Point3D { x: number; y: number; z: number }
const p2: Point = new Point3D()
接口兼容性代码示例:
interface Point { x: number; y: number }
class Point4D { x: number; y: number; z: number }
let p1: Point
p1 = new Point4D
函数之间的兼容性
需要考虑:参数个数、参数类型、返回值类型
1、参数个数,参数多的兼容参数少的(或者说:参数少的可以赋值给参数多的)
2、参数类型,相同位置的参数类型要相同(原始类型)或兼容(对象类型)
3、返回值类型,只关注返回值类型本身即可,如果返回值类型是原始类型,此时两个类型要相同;如果返回值类型是对象类型,此时成员多的可以赋值给成员少的
参数个数代码示例:
type F1 = (a: number) => void
type F2 = (a: number, b: number) => void
let f1: F1
let f2: F2
//@ts-ignore
f2 = f1
注意:
我也不是很清楚为什么我写的f2=f1会有校验报错(在赋值前使用了变量f1),可以在该语句上方加一个忽略ts校验的一个注释://@ts-ignore
这样就不会飘红色波浪线了
如果添加了这个注释,那么如果下面那段代码真的有bug也是不会提示的
参数类型代码示例:
type F3 = (a: number) => string
type F4 = (a: number) => string
let f3: F3
let f4: F4
f4=f3
返回值类型代码示例:
type F5 = () => { name: string }
type F6 = () => { name: string; age: number }
let f5: F5
let f6: F6
f5 = f6