typescript中的兼容性(十二)

自动类型推论

概述

  • 根据初始化进行类型推论
    • 不用明确告诉编译器具体是什么类型,编译器就知道是什么类型
    • 根据初始化值自动推断
    • 注意点: 如果先定义在初始化,那么是无法自动推断
    // 相当于 let x: (number | null)[] = [0,1,null]
    let x = [0,1,null]
    // x = [20,30,60,null,"zs"]  // error,"zs"是属于字符串类型
    
    // 不能进行类型推论
    let uage;
    uage = 123
    uage = true
    
  • 上下文类型推断
    • 上下文类型推断
    window.onmousedown = function(mouseEvent){
      mouseEvent.button
      mouseEvent.clientX
    }
    

对象类型兼容性

对象类型兼容性(可多不可少)

interface INameTest{
  name: string
}

let n1 = {name: "法外狂徒张三"}
let n2 = {name: "zs",age: 18}
let n3 = {age: 19}

let val: INameTest
val = n1
val = n2
// val = n3 // error,类型 "{ age: number; }" 中缺少属性 "name",但类型 "INameTest" 中需要该属性

对象类型兼容性(类型必须一一对应)

// 注意点  类型必须一一对应,ts内部会进行递归检查
interface ITestInfo{
  name: string
  children: {
    age: number
  }
}

let p1 = {name: 'zs',children: {age: 19}}
let p2 = {name: 'zs',children: {age: true}}

let person: ITestInfo;
person = p1
// person = p2 //error,不能将类型“{ name: string; children: { age: boolean; }; }”分配给类型“ITestInfo”。在这些类型中,"children.age" 的类型不兼容。不能将类型“boolean”分配给类型“number”

函数类型兼容性

参数个数

let func1 = (x: number,b: string) =>{}
let func2 = (x: number) =>{}

// 注意点: 可多不可少
func1 = func2
// func2 = func1 // error,不能将类型“(x: number, b: string) => void”分配给类型“(x: number) => void”

参数类型

let func3 = (x: number) =>{}
let func4 = (x: string) =>{}
let func5 = (x: number) =>{}


// 注意点: 参数类型一致
// func3 = func4 // error,不能将类型“(x: string) => void”分配给类型“(x: number) => void”。参数“x”和“x” 的类型不兼容。不能将类型“number”分配给类型“string”
func3 = func5

参数返回值

let func6 = (): number => 23
let func7 = (): number => 13
let func8 = (): string => "返回值类型的兼容性"

// 注意点: 返回值类型必须一致
func6 = func7
// func6 = func8 // error,不能将类型“() => string”分配给类型“() => number”。不能将类型“string”分配给类型“number”

双向协变

// 1.参数的双向协变
let funct1 = (x: number) => {}
let funct2 = (x: (number | string)) => {}


// 注意点: 可以将多的赋值给少的
funct1 = funct2
// funct2 =funct1  // 不能将类型“(x: number) => void”分配给类型“(x: (number | string)) => void”。参数“x”和“x” 的类型不兼容。不能将类型“string | number”分配给类型“number”。不能将类型“string”分配给类型“number”

// 2.返回值的双向协变

let funct3 = (x: boolean): (number | string) => x? 18 : 'zs'
let funct4 = (x: boolean): number => 18

// 注意点: 不能将返回值是联合类型的赋值给具体的
funct3 = funct4
// funct4 = funct3 // error,不能将类型“(x: boolean) => (number | string)”分配给类型“(x: boolean) => number”。不能将类型“string | number”分配给类型“number”。不能将类型“string”分配给类型“number”

函数重载

function add(x: number,y: number): number
function add(x: string,y: string): string
function add(x: any,y: any): any {
  return x+y
}

function sub(x: number,y: number): number
function sub(x: any,y: any): any{
  return x-y
}
// 注意点: 不能将重载少,赋值给重载多的(包含关系)

let fna = add
let fns = sub
// fna = fns //error,不能将类型“(x: number, y: number) => number”分配给类型“{ (x: number, y: number): number; (x: string, y: string): string; }”。参数“x”和“x” 的类型不兼容。不能将类型“string”分配给类型“number”
fns = fna

可选参数及剩余参数

// 当一个函数有剩余参数的时候,被当做无限个可选参数
function func(args: any[],callback: (...args: any[]) => void) {}
func([1,2],(x,y,z) => console.log(x+y+z))
func([1,2],(x?,y?) => console.log(x+y))
func([1,2],(x,y?,z?) => console.log(x+y))


枚举类型知识补充

数据枚举类型

  • 数字枚举的取值可以是字面量,也可以是常量,也可以是计算的结果
  • 如果采用字面量对第一个成员进行赋值,下面的成员会自动递增
  • 如果采用常量计算结果进行赋值,则下面的成员也必须初始化
// 数字枚举
enum Gender {
  Male,
  Female
}
console.log(Gender.Male,Gender.Female) // 0 1
console.log(Gender[0]) // Male


const val = 100
const num = () => 200
enum Gender_1 {
  // 常量
  Male = val,
  // 计算结果
  Female = num()
}

字符串枚举类型

  • 如果采用字面量对第一个成员进行赋值,下面的成员也必须赋值
  • 采用[index]的形式不能获取到内容,需要传入[key]
  • 字符串枚举不能使用常量计算结果给枚举值赋值
  • 它可以使用内部的其他枚举值来赋值
enum Direction {
  up = "UP",
  down = "DOWN"
}
console.log(Direction.up)// UP
// console.log(Direction[0]) // error,元素隐式具有 "any" 类型,因为类型为 "0" 的表达式不能用于索引类型 "typeof Direction"。类型“typeof Direction”上不存在属性“0”
console.log(Direction["up"])// UP

const str = "法外狂徒张三"
const res = () => "鬼脚七"
enum Star{
  // desc = str //error,只有数字枚举可具有计算成员,但此表达式的类型为“"法外狂徒张三"”。如果不需要全面性检查,请考虑改用对象文本
  // desc = res //error,只有数字枚举可具有计算成员,但此表达式的类型为“() => string”。如果不需要全面性检查,请考虑改用对象文本
  desc = "太极宗师",
  tagDesc = desc
}

异构枚举(数字+字符串)

  • 如果是字符串枚举,那么无法通过原始值获取到枚举值
enum  Person{
  Male = 1,
  Female = '女'
}
console.log(Person.Male) // 1
console.log(Person.Female) // 女
console.log(Person[0]) // undefined
console.log(Person["Male"]) // 1

把枚举成员当作类型来使用

enum Gender_2{
  Male,
  Female
}
interface PersonInfo{
  sex: Gender_2 // sex: (Gender_2.Male | Gender_2.Female)
}

class Persons implements PersonInfo{
  sex: Gender_2.Female = 1
}

枚举类型兼容性

数字枚举与数字兼容

enum Gender{
 Male,
 Female 
}

let value: Gender;
value = Gender.Male
value = 100

数字枚举与数字枚举不兼容

enum Gender{
 Male,
 Female 
}

enum Animal{
  Dog,
  Cat
}

let value: Gender
value = Gender.Female
// value = Animal.Dog // error,不能将类型“Animal.Dog”分配给类型“Gender”


字符串枚举与字符串不兼容

enum Gender{
  Male = "法外狂徒张三",
  Female = "李寒冰"
}
let value: Gender
value = Gender.Male
value = Gender.Female

// value = "赵玉道" // error,不能将类型“"赵玉道"”分配给类型“Gender”



类的兼容性

  • 类的工作方式与对象字面类型和接口类似,但有一个不同点: 他们同时具有静态实例类型时,当比较一个类类型的两个对象时,只有实例的成员被比较静态成员构造函数不影响兼容性
  • 一个类中的私有成员保护成员会影响兼容性。当一个类的实例被检查兼容性时,如果目标类型包含一个私有成员,那么原类型也必须包含一个源自同一个类的私有成员(保护成员同上)
  • public可多不可少
  • private/protected不能相互赋值

类的兼容性—可多不可少

// 可多不可少
class Animal{
  feet: number
  age: number
  constructor(feet: number,age: number){
    this.feet = feet
    this.age = age
  }
}
class Size{
  feet: number
  constructor(numFeet: number){
    this.feet = numFeet
  }
}
let anm: Animal
let si: Size

// anm = si // error,类型 "Size" 中缺少属性 "age",但类型 "Animal" 中需要该属性。
si = anm

类的兼容性—private/protected

class Animal{
  private feet: number
  constructor(name: string,numFeet: number){
    this.feet = numFeet
  }
}
class Size{
  private feet: number
  constructor(numFeet: number){
    this.feet = numFeet
  }
}
let anm: Animal
let si: Size

// si = anm // error,不能将类型“Animal”分配给类型“Size”。类型具有私有属性“feet”的单独声明
// anm = si // 不能将类型“Size”分配给类型“Animal”。类型具有私有属性“feet”的单独声明

泛型的兼容性

// TS是一个结构化的类型系统,类型参数只在作为成员类型的一部分被消耗是影响到结果类型
interface Empty<T> {}

let x: Empty<number>
let y: Empty<string>

x = y
y = x


interface NotEmpty<T>{
  data: T
}

let x1: NotEmpty<string>
let y1: NotEmpty<number>

// x1 = y1 // error,不能将类型“NotEmpty<number>”分配给类型“NotEmpty<string>”。不能将类型“number”分配给类型“string”
// y1 = x1 // error,不能将类型“NotEmpty<string>”分配给类型“NotEmpty<number>”。不能将类型“string”分配给类型“number”
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值