弱类型语言存在的问题
- 调用不存在的变量不会立即报错,只有程序运行时才会发现错误
- 函数的传入参数类型不明确,可能会导致函数功能发生变化
- 对象索引器的错误调用
强类型语言的优势
- 错误更早暴露
- 代码更智能,编码更准确
- 重构更牢靠
- 减少不必要的类型判断
变量类型
any和mixed:都表示任意类型,但any定义的变量为弱类型,mixed定义的变量为强类型,即可以传入任意类型的值,但在内部处理的时候仍然需要判断,比any更安全
TypeScript
typescript初始化
- 使用yarn tsc 文件名编译ts文件,之后会生成一个js文件,这个js文件里会将es新特性和ts的注解重新编译(编译es新特性可以在配置文件中修改)
- yarn tsc --init会初始化一个tsconfig配置文件,这个文件只有在编译整个项目(yarn tsc)的时候才会生效
- tsconfig的lib是用来配置默认标准库的
typescript的使用
作用域
ts的默认作用域在整个项目中,也就是两个文件中使用同名变量会出错。
解决方法:
- 在文件中形成局部作用域,也就是立即执行函数,在函数内部定义变量
- 使用export{}使文件形成单独的模块作用域
object类型
ts中的object类型泛指数组、对象、函数等所有类型(不包括原始类型)
enum枚举类型
设置固定的枚举元素和其对应的枚举值,枚举值可以是数字和字符串,数字枚举可以不赋值,默认从0开始,后面的枚举值依次加1
enum enumStatus {
enum1 = 0,
enum2,
enum3
}
类型断言
ts会自动推断某些运算结果的类型,我们可以使用as来给推断的类型进行断言,使之可以顺利进行后面的步骤
export {}
const nums = [1, 2, 3, 4, 5]
// 这里ts会推断res为number或undefined
const res = nums.find(i => i >1)
// ts推断出运算结果可能为undefined时就会报语法错误
// const square = res * res
// 类型断言
const num1 = res as number
const square1 = num1 * num1
接口
用来约束对象的结构
interface Post {
title: string
content: string
subtitle?: string //可选成员
readonly summary: string //只读成员,不可修改
}
function printPost (post: Post) {
console.log(post.title)
console.log(post.content)
}
printPost({
title: 'Hello',
content: 'TypeScript',
summary: 'Summary'
})
类
export {}
class Person {
// 构造函数里的值必须先定义才能使用
name: string
// 私有成员外部无法访问
private age: number
// 外部无法访问,允许在子类访问该成员
protected gender: boolean
constructor(name: string, age: number) {
this.name = name
this.age = age
this.gender = true
}
sayHi(msg: string): void {
console.log(`I am ${this.name}, ${msg}`)
console.log(this.age)
}
}
const tom = new Person('tom', 18)
tom.sayHi('hello')
// 会语法报错
console.log(tom.age)
类和接口
- 不同的类存在某些共同的属性或方法,可以把相同的部分抽象成公共接口
- 接口最好遵循单一原则,一个接口只实现一个功能
interface Eat {
eat (food: string): void
}
interface Run {
run (distance: number): void
}
//类中必须要有接口的属性或方法
class Person implements Eat, Run {
eat (food: string): void {
console.log(`优雅的进餐:${food}`)
}
run (distance: number) {
console.log(`直立行走:${distance}`)
}
}
class Animal implements Eat, Run {
eat (food: string): void {
console.log(`呼噜呼噜的吃:${food}`)
}
run (distance: number) {
console.log(`爬行:${distance}`)
}
}
抽象类
在定义类前加上abstract关键字使之成为抽象类,这个类就只能被继承不能被实例化,抽象类中可以使用abstract关键字定义抽象方法,抽象方法不需要有方法体,并且定义了就必须在子类实现这个抽象方法
泛型
定义方法时把不能明确的类型定义成参数()传递,使这个方法可以最大程度的复用