[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 -- 去除指定的鍵值