TS学习笔记7:类型推论和兼容性

103 阅读2分钟

点击此处访问本文所属专栏

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  // 接口定义了一个空对象时,使用泛型定义的对象可以兼容