TS中的兼容性
自动类型推论概述
对象类型兼容性对象类型兼容性(可多不可少)对象类型兼容性(类型必须一一对应)
函数类型兼容性参数个数参数类型参数返回值双向协变函数重载可选参数及剩余参数
枚举类型知识补充数据枚举类型字符串枚举类型异构枚举(数字+字符串)把枚举成员当作类型来使用
枚举类型兼容性数字枚举与数字兼容数字枚举与数字枚举不兼容字符串枚举与字符串不兼容
类的兼容性类的兼容性---可多不可少类的兼容性---private/protected
泛型的兼容性
自动类型推论
概述
根据初始化进行类型推论
不用明确告诉编译器具体是什么类型,编译器就知道是什么类型根据初始化值自动推断注意点: 如果先定义在初始化,那么是无法自动推断的 // 相当于 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
let x: Empty
let y: Empty
x = y
y = x
interface NotEmpty
data: T
}
let x1: NotEmpty
let y1: NotEmpty
// x1 = y1 // error,不能将类型“NotEmpty
// y1 = x1 // error,不能将类型“NotEmpty
推荐文章
发表评论