1. 类型推论
未给变量指定类型,ts会自动为变量分配类型
let name = 'Kael'
name = 123 // error
多类型联合
let arr5 = [1 , 'a']
arr5 = [2, 'b']
arr5 = [true] // error
上下文类型
window.onmousedown = (e) => {
console.log(e)
// 此时e是mouseEvent类型,代码会自动检测出mouseEvent类型上没有a属性
console.log(e.a) // error
}
2. 类型兼容性
一个类型可以赋值另一个类型时,这两个类型是兼容的
2.1 接口的兼容性
只要目标类型中声明的属性变量在源类型中都存在就是兼容的,只能多,不能少。 接口定义的深层次的类型,对象在检测时会递归检测。
interface InfoInterface {
name: string
}
let infos: InfoInterface
const infos1 = {
name: 'Kael'
}
const infos2 = {
age: 18
}
const infos3 = {
name: 'Kael',
age: 18
}
infos = infos1 // 通过,对象完全符合接口定义的内容
infos = infos2 // error,对象没有name属性
infos = infos3 // 通过,已经有name属性,多了一个age属性也无所谓
2.2 函数的参数个数
let x = (a:number) => 0
let y = (b:number, c:string) => 0
y = x // 通过
x = y // error y的参数个数必须小于x的参数个数
2.3 函数的参数类型
let x = (a: number) => 0
let y = (b:string) => 0
x = y // error 参数类型必须一致
2.4 可选参数和剩余参数
const getSum = (arr:number[], callback: (...args:number[]) => number): number => {
return callback(...arr)
}
const res = getSum([1,2,3],(...args: number[]) : number => args.reduce((a,b) => a + b))
const res2 = getSum([1,2,3],(arg1:number, arg2:number, arg3:number) : number => arg1 + arg2 + arg3)
console.log(res) // 6
console.log(res2) // 6
2.5 函数参数双向协变
双向协变可在项目中配置为禁止
let funcA = (arg: number | string): void => {}
let funcB = (arg: number): void => {}
funcA = funcB // 通过
funcB = funcA // 通过
2.6 函数返回值类型
let x1 = (): string | number=> 0
let y1 = (): string => 'a'
x1 = y1 // 通过, x1的返回值类型既可以是string也可以是number
y1 = x1 // error
2.7 函数重载
function merge (arg1: number, arg2:number): number
function merge (arg1: string, arg2:string): string
function merge (arg1: any, arg2:any) {
return arg1 + arg2
}
function sum (arg1: number, arg2:number): number
function sum (arg1: any, arg2:any):any {
return arg1 + arg2
}
let func = merge
func = sum
2.8 数字枚举类型的兼容性
数字枚举类型和数字类型互相兼容
enum StatusEnum {
On,
Off,
}
enum AnimalEnum {
Dog,
Cat
}
let s = StatusEnum.On
s = 1 // 类型兼容
s = AnimalEnum.Dog // error
2.9 类的兼容
class AnimalClass {
public static age: number
constructor(public name: string) {}
}
class PeopleClass {
public static age: number
constructor(public name: string) {}
}
let animal: AnimalClass
let people: PeopleClass
animal = people // 将类作为类型,实际检测的是类的实例,两个类的类型兼容,因此赋值操作没有问题
用privae和protected修饰的类成员,会对类型校验造成影响
class ParentClass {
private age: number
constructor() {}
}
class ChildClass extends ParentClass {
constructor(){
super()
}
}
class OtherClass {
private age: number
constructor() {}
}
const children: ParentClass = new ChildClass() // 子类可以赋值给父类的值
const other: ParentClass = new ChildClass() // error 类型具有私有属性
2.10 泛型的兼容性
interface Data<T> {}
let data1: Data<number>
let data2: Data<string>
data1 = data2 // 接口定义了一个空对象时,使用泛型定义的对象可以兼容