[TOC]
>[success] # 子类型都兼容父类型
~~~
1.所有的子类型与它的父类型都兼容
~~~
~~~
// 案例一
let num: number
let one: 1 = 1
num = one
// 案例二 IPar 是父接口虽然结构上看比IChild少
// 但是子类型赋值父类型没问题
interface IPar {
name: string
}
interface IChild extends IPar {
id: number
}
let Par: IPar
let Child: IChild = { id: 1, name: '12' }
Par = Child
// Dog 继承了Animal 同理 最后DOG 可以赋值给Animal
class Animal {
name: string = 'w'
}
class Dog extends Animal {
run() {}
}
let animal:Animal
let dog = new Dog()
animal = dog
~~~
>[success] # 结构类型
~~~
1.如果x要兼容y,那么y至少具有与x相同的属性',你可以把'多的赋值给少的',但是不能'把少'的赋值
给'多的'
~~~
>[danger] ##### 定义类型方式不同但字段参数类型都相同
~~~
1.x要兼容y,那么y至少具有与x相同的属性 满足即下面都能互相兼容
~~~
~~~
class A {
name = 1
}
interface B {
name: number
}
type C = {
name: number
}
// 字面量
const d = { name: 2 }
let a: A = d
let b: B = a
let c: C = b
~~~
>[danger] ##### y 拥有x 所有属性且拥有y不具备属性
~~~
1.一个类型不仅拥有另外一个类型全部的属性和方法,还包含其他的属性和方法(如同继承自另外一个类型的子类一样),
那么前者是可以兼容后者的'多的赋值给少的'
~~~
~~~
class A {
name = 1
age = 1
}
interface B {
name: number
}
type C = {
name: number
}
// 字面量
const d = { name: 2 }
let b: B = new A()
let c: C = new A()
// 报错
let a: A = d // 报错 少的赋值给多的了
~~~
>[danger] ##### 对象字面的 freshness 特性
~~~
1.上面案例将'多的赋值给少的' 有特例,如果是字面量的对象不能直接兼容
~~~
* 非字面量的情况完美兼容
~~~
class A {
name = 1
age = 1
}
interface B {
name: number
}
let b: B = new A()
~~~
* 字面量情况
~~~
interface B {
name: number
}
let b: B = { id: 1, name: 1 } // 报错
// 需要先打破freshness 特性,即赋值一次做中转
const a = { id: 1, name: 1 }
b = a // ok
// 或者使用断言,断言必须是子父关系 将低等级断言给高等级的
// 其实满足之前说到多的可以兼容少的
const c: B = { id: 1, name: 1 } as B
// interface B {
// name: number
// age: number
// }
// // 这样断言成功因为 { age: 1 } 是B的子集
// const c: B = { age: 1 } as B
~~~
>[success] # 类
~~~
1.如果两个类包含私有、受保护的属性和方法,则仅当这些属性和方法源自同一个类,它们才兼容
2.类有静态部分和实例部分的类型。 比较两个类类型的对象时,只有实例的成员会被比较。
静态成员和构造函数不在比较的范围内
~~~
>[danger] ##### 解释第一条
~~~
class C1 {
name = '1'
private id = 1
protected age = 30
}
class C2 {
name = '2'
private id = 1
protected age = 30
}
let InstC2: C2 = new C1() // 报错
~~~
>[danger] ##### 解释第二条
~~~
1.向下面的案例'AnimalClass ' 和'PeopleClass',中 因为static 是静态类方法所以他们age属性是不影响他们相互赋值
,比较的都是实例成员,也因此'FoodIsClass ' 的name属性类型和另外两个不一致不能相互赋值
~~~
~~~
class AnimalClass {
public static age: number
constructor(public name: string) {}
}
class PeopleClass {
public static age: string
constructor(public name: string) {}
}
class FoodIsClass {
constructor(public name: number) {}
}
let animal: AnimalClass = new AnimalClass('w')
let people: PeopleClass = new PeopleClass('w')
let food: FoodIsClass = new FoodIsClass(1)
people = animal
// animal = food // 报错
~~~
>[success] # 泛型
~~~
1.如果定义接口里面没东西,那么泛型类型可以交叉赋值,如果有了东西类型不一致就报错了,简单理解定义了却
没在实际使用这个泛型则都兼容
~~~
~~~
interface Empty<T> {
}
let x: Empty<number>;
let y: Empty<string>;
x = y;
interface NotEmpty<T> {
data: T;
}
let x: NotEmpty<number>;
let y: NotEmpty<string>;
x = y; // Error, because x and y are not compatible
~~~
>[success] # 函数兼容 -- 函数参数
~~~
1.参数个数一致,类型不同,是不能相互赋值的
2.参数个数不一致,相同类型参数的位置也不一致,是不可以相互赋值的
3.参数个数不一致,相同类型参数的位置一致,可以相互赋值,但是'只能把少的赋值给多的'
~~~
>[danger] ##### 首先参数个数一致,类型不同
~~~
let xx = (a: number) => 0
let yy = (a: string) => 0
// xx = yy // 报错参数类型不一致
~~~
>[danger] ##### 参数个数不一致,相同类型参数的位置也不一致
~~~
let x = (c: number) => 0
let y = (a: string, b: number) => 0
// xx = yy // 报错
~~~
>[danger] ##### 参数个数不一致,相同类型参数的位置一致,可以相互赋值,但是'只能把少的赋值给多的
~~~
1.解释为什么只能把少的赋值给多的,你把少的赋值给多,多的那个没被赋值的参数相当于'undefind' 没有影响,
但是你把多的赋值给少的,少的无缘无故多了一个参数那就报错了
~~~
~~~
let x = (a: number) => 0
let y = (a: number,b:string) => 0
y=x // 把少的 给多的,多的可以只用一个参数另一不用
// x = y // 把多的参数,赋值给少参数,因为x定义只有一个a,你多给他一个b他也用不了
~~~
>[danger] ##### 函数兼容 -- 剩余参数
~~~
1.当一个函数有剩余参数时,它被当做无限个可选参数
~~~
~~~
const getSum = (nlist:number[],callback:(...args:number[])=>number)=>{
callback(...nlist)
}
getSum([1,2,3],(...args:number[])=>{
const sum = args.reduce((a, b) => a + b)
console.log(sum) // 6
return sum
})
getSum([1, 2, 3], (n1:number,n2:number) => {
console.log(n1+n2)
return n1+n2
})
~~~
>[danger] ##### 函数兼容 -- 函数参数双向协变
~~~
1.当A的参数类型不确定,B 的参数类型为A中不确定参数类型中的一个。可以吧多类型赋值给少类型的
~~~
~~~
let funcA = (arg1: number | string) => { }
let funcB = (arg1: number ) => { }
// funcA = funcB // 错误的
funcB = funcA
~~~
>[danger] ##### 函数兼容 -- 返回值类型
~~~
1.函数返回类型可以把少的赋值给多的,多的不能赋值给少的
~~~
~~~
let funcTypeA = (): string | number => 0
let funcTypeB = (): number => 0
funcTypeA = funcTypeB
// funcTypeB = funcTypeA // 报错
~~~
>[danger] ##### 函数兼容 -- 函数的重载
~~~
1.重载类型不一致怎么赋值都是错
~~~
~~~
function merge(n1: number, n2: number): number
function merge(n1: string, n2: string): string
// 虽然是any 但是只能是 string 或者 number
function merge(n1:any,n2:any):any{
return n1+n2
}
function sum(n1: number, n2: number): number
function sum(n1: any, n2: any): any {
return n1 + n2
}
// 问题重载类型不一致怎么赋值都是错
// merge = sum // 报错
// sum = merge // 报错
~~~
>[success] # 枚举的类型兼容性
~~~
枚举与数字类型相互兼容:
enum Status {
Ready,
Waiting
}
let status = Status.Ready;
let num = 0;
status = num;
num = status;
~~~
- TypeSprict -- 了解
- TS-- 搭建(一)webpack版本
- TS -- 搭建(二)直接使用
- TS -- 基本类型
- ts -- 类型推导和字面量类型
- ts -- 类型扩展和类型缩小
- ts -- any场景
- ts -- 使用unknown 还是 any
- ts -- any/never/unknown
- ts -- 断言
- ts -- 类型大小写疑惑
- ts -- 数组类型 [] 还是泛型疑惑
- TS -- 枚举
- 外部枚举
- TS -- 函数
- ts -- 重载作用
- ts -- 05 this is
- 解构
- TS -- 接口
- 绕过接口的多余参数检查
- Interface 与 Type 的区别
- TS -- 类
- ts -- 类作为类型
- TS -- 交叉和联合 类型
- ts -- 交叉类型
- ts -- 联合类型
- ts -- 交叉和联合优先级
- ts -- 类型缩减
- TS -- 什么是泛型
- ts -- 泛型函数表达式/函数别名/接口
- ts -- 泛型类
- ts -- extends 泛型约束
- ts -- 泛型new
- ts -- Ts的泛型
- TS -- 缩小类型详解类型守卫
- TS -- 类型兼容性
- TS -- 命名空间与模块化
- ts -- 模块化
- ts -- 命名空间
- TS -- 工具方法
- Record -- 一组属性 K(类型 T)
- Exclude -- 从联合类型中去除指定的类
- Extract -- 联合类型交集
- NonNullable -- 从联合类型中去除 null 或者 undefined
- Partial -- 将所有属性变为可选
- Required -- 所有属性变为必填
- Readonly -- 所有属性只读
- Pick -- 类型中选取出指定的键值
- Omit -- 去除指定的键值