## 8.結構類型系統
### 8.1 接口的兼容性
* 如果傳入的變量和聲明的類型不匹配,TS就會進行兼容性檢查
* 原理是`Duck-Check`,就是說只要目標類型中聲明的屬性變量在源類型中都存在就是兼容的
~~~
interface Animal{
name:string;
age:number;
gender:number
}
let a1 = {
name:'zhufeng',
age:10,
gender:0
}
interface Person{
name:string;
age:number
}
////- 要判斷目標類型`Person`是否能夠兼容輸入的源類型`Animal`
function getName(p:Person):string{
return p.name;
}
getName(a1);
//只有在傳參的時候兩個變量之間才會進行兼容性的比較,賦值的時候并不會比較,會直接報錯
let x:Person = {
name:'zhufeng',
age:10,
gender:0
}
~~~
### 8.2 基本類型的兼容性
~~~
//基本數據類型也有兼容性判斷
let num : string|number;
let str:string;
num = str;
//只要有toString()方法
let num2 : {
toString():string
}
let str2:string;
num2 = str2;
~~~
### 8.3 類的兼容性
* 在TS中是結構類型系統,只會對比結構而不在意類型
~~~
class Animal{
name:string
}
class Bird extends Animal{
swing:number
}
let a:Animal;
a = new Bird();
let b:Bird;
//并不是父類兼容子類,子類不兼容父類
b = new Animal();
~~~
~~~
class Animal{
name:string
}
//如果父類和子類結構一樣,也可以的
class Bird extends Animal{}
let a:Animal;
a = new Bird();
let b:Bird;
b = new Animal();
~~~
~~~
//甚至沒有關系的兩個類的實例也是可以的
class Animal{
name:string
}
class Bird{
name:string
}
let a:Animal ;
a = new Bird();
let b:Bird;
b = new Animal();
~~~
### 8.4 函數的兼容性
* 比較函數的時候是要先比較函數的參數,再比較函數的返回值
* 參數可以省略
~~~
type sumFunc = (a:number,b:number)=>number;
let sum:sumFunc;
function f1(a:number,b:number){
return a+b;
}
sum = f1;
//可以省略一個參數
function f2(a:number):number{
return a;
}
sum = f2;
//可以省略二個參數
function f3():number{
return 0;
}
sum = f3;
//多一個參數可不行
function f4(a:number,b:number,c:number){
return a+b+c;
}
sum = f4;
~~~
~~~
type GetPerson = ()=>{name:string,age:number};
let getPerson:GetPerson;
//參數一樣可以
function g1(){
return {name:'zhufeng',age:10};
}
getPerson = g1;
//多一個屬性也可以
function g2(){
return {name:'zhufeng',age:10,gender:'male'};
}
getPerson = g2;
//少一個屬性不行
function g3(){
return {name:'zhufeng'};
}
getPerson = g3;
//因為有可能要調用返回值上的方法
getPerson().age.toFixed();
~~~
### 8.5 函數參數的雙向協變
* 函數的參數中目標兼容源,或者源兼容目標都可以,只要有一個成立就可以
~~~
type LogFunc = (a:number|string)=>void;
let log:LogFunc;
function log1(a:number){
console.log(a);
}
//在這里定義的參數類型兼容實際的參數類型
log = log1;
function log2(a:number|string|boolean){
console.log(a);
}
//在這里實際的參數類型兼容定義的參數類型
log = log2;
~~~
### 8.6 泛型的兼容性
* 泛型在判斷兼容性的時候會先判斷具體的類型,然后再進行兼容性判斷
~~~
//接口內容為空沒用到泛型的時候是可以的
interface Empty<T>{}
let x:Empty<string>;
let y:Empty<number>;
x = y;
//接口內容不為空的時候不可以
interface NotEmpty<T>{
data:T
}
let x1:NotEmpty<string>;
let y1:NotEmpty<number>;
x1 = y1;
interface NotEmptyString{
data:string
}
interface NotEmptyNumber{
data:number
}
let xx3:NotEmptyString;
let yy3:NotEmptyNumber;
xx3 = yy3;
~~~
### 8.7 枚舉的兼容性
* 枚舉類型與數字類型兼容,并且數字類型與枚舉類型兼容
* 不同枚舉類型之間是不兼容的
~~~
//數字可以賦給枚舉
enum Colors {Red,Yellow}
let c:Colors;
c = Colors.Red;
c = 1;
c = '1';
//枚舉值可以賦給數字
let n:number;
n = 1;
n = Colors.Red;
~~~
## 9.類型保護
* 類型保護就是一些表達式,他們在編譯的時候就能通過類型信息確保某個作用域內變量的類型
* 類型保護就是能夠通過關鍵字判斷出分支中的類型
### 9.1 typeof 類型保護
~~~
function double(input:string|number|boolean){
if(typeof input === 'string'){
return input + input;
}else {
if(typeof input === 'number'){
return input*2;
}else{
return !input;
}
}
}
~~~
### 9.2 instanceof類型保護
~~~
class Animal{
name:string;
}
class Bird extends Animal{
swing:number
}
function getName(animal:Animal){
if(animal instanceof Bird){
console.log(animal.swing);
}else{
console.log(animal.name);
}
}
~~~
### 9.3 null保護
* 如果開啟了`strictNullChecks`選項,那么對于可能為null的變量不能調用它上面的方法和屬性
~~~
function getFirstLetter(s:string|null){
//第一種方式是加上null判斷
if(s == null){
return '';
}
//第二種處理是增加一個或的處理
s = s || '';
return s.charAt(0);
}
//它并不能處理一些復雜的判斷,需要加鏈判斷運算符
function getFirstLetter2(s:string|null){
function log(){
console.log(s!.trim());
}
s = s || '';
log();
return s.charAt(0);
}
~~~
### 9.4 鏈判斷運算符
* 鏈判斷運算符是一種先檢查屬性是否存在,再嘗試訪問該屬性的運算符,其符號為 ?.
* 如果運算符左側的操作數 ?. 計算為 undefined 或 null,則表達式求值為 undefined 。否則,正常觸發目標屬性訪問,方法或函數調用。
~~~
a?.b; //如果a是null/undefined,那么返回undefined,否則返回a.b的值.
a == null ? undefined : a.b;
a?.[x]; //如果a是null/undefined,那么返回undefined,否則返回a[x]的值
a == null ? undefined : a[x];
a?.b(); // 如果a是null/undefined,那么返回undefined
a == null ? undefined : a.b(); //如果a.b不函數的話拋類型錯誤異常,否則計算a.b()的結果
a?.(); //如果a是null/undefined,那么返回undefined
a == null ? undefined : a(); //如果A不是函數會拋出類型錯誤
//否則 調用a這個函數
~~~
### 9.5 可辨識的聯合類型
* 就是利用聯合類型中的共有字段進行類型保護的一種技巧
* 相同字段的不同取值就是可辨識
~~~
interface WarningButton{
class:'warning',
text1:'修改'
}
interface DangerButton{
class:'danger',
text2:'刪除'
}
type Button = WarningButton|DangerButton;
function getButton(button:Button){
if(button.class=='warning'){
console.log(button.text1);
}
if(button.class=='danger'){
console.log(button.text2);
}
}
~~~
### 9.6 in操作符
* in 運算符可以被用于參數類型的判斷
~~~
interface Bird {
swing: number;
}
interface Dog {
leg: number;
}
function getNumber(x: Bird | Dog) {
if ("swing" in x) {
return x.swing;
}
return x.leg;
}
~~~
### 9.7 自定義的類型保護
* TypeScript 里的類型保護本質上就是一些表達式,它們會在運行時檢查類型信息,以確保在某個作用域里的類型是符合預期的
* 要自定義一個類型保護,只需要簡單地為這個類型保護定義一個函數即可,這個函數的返回值是一個類型謂詞
* 類型謂詞的語法為`parameterName is Type`這種形式,其中`parameterName`必須是當前函數簽名里的一個參數名`
~~~
interface Bird {
swing: number;
}
interface Dog {
leg: number;
}
//沒有相同字段可以定義一個類型保護函數
function isBird(x:Bird|Dog): x is Bird{
return (<Bird>x).swing == 2;
return (x as Bird).swing == 2;
}
function getAnimal(x: Bird | Dog) {
if (isBird(x)) {
return x.swing;
}
return x.leg;
}
~~~
- 文檔簡介
- 基礎面試題【珠峰2019.8】
- P01_call,aplly區別
- P02_綜合面試題講解2-2
- P03_箭頭函數和普通函數區別-綜合面試題講解2-3
- P05_實現indexOf
- P06_綜合面試題講解2-6
- P07_URL解析題
- P08_原型題
- P09_圖片延時加載
- P10_正則-包含數字字母下劃線
- P11_綜合面試題講解2-11
- P12_英文字母加空格
- P13_數組扁平化并去重
- P14_模擬實現new
- P15_合并數組
- P16_定時器,打印012345
- P17_匿名函數輸出值問題
- P18_a在什么情況下打印輸出+1+1+1
- P19_對數組的理解
- P20_冒泡排序
- P21_插入排序
- P22_快速排序
- P23_銷售額存在對象中
- P24_求數組的交集
- P25_旋轉數組
- P26_ [函數柯理化思想]
- P27_ [柯理化函數的遞歸]
- 網絡協議【珠峰2019.6】
- TypeScript+Axios入門+實戰【珠峰2019.11】
- 1.數據結構
- 2.函數和繼承
- 3.裝飾器
- 4.抽象類-接口-泛型
- 05-結構類型系統和類型保護
- 06-類型變換
- AST-抽象語法樹
- React性能優化【珠峰2019.10】
- 1-react性能優化
- 2-react性能優化
- 3.react-immutable
- React Hooks【珠峰2019.12】
- 前端框架及項目面試
- 第07章 React 使用
- 7-1 React使用-考點串講
- 7-2 JSX基本知識點串講
- 7-3 JSX如何判斷條件和渲染列表
- 7-4 React事件為何bind this
- 7-5 React事件和DOM事件的區別
- 7-6 React表單知識點串講
- 7-7 React父子組件通訊
- 7-8 setState為何使用不可變值
- 7-9 setState是同步還是異步
- 7-10 setState合適會合并state
- 7-11 React組件生命周期
- 7-12 React基本使用-知識點總結和復習
- 7-13 React函數組件和class組件有何區別
- 7-14 什么是React非受控組件
- 7-15 什么場景需要用React Portals
- 7-16 是否用過React Context
- 7-17 React如何異步加載組件
- 7-18 React性能優化-SCU的核心問題在哪里
- 7-19 React性能優化-SCU默認返回什么
- 7-20 React性能優化-SCU一定要配合不可變值
- 7-21 React性能優化-PureComponent和memo
- 7-22 React性能優化-了解immutable.js
- 7-23 什么是React高階組件
- 7-24 什么是React Render Props
- 7-25 React高級特性考點總結
- 7-26 Redux考點串講
- 7-27 描述Redux單項數據流
- 7-28 串講react-redux知識點
- 7-29 Redux action如何處理異步
- 7-30 簡述Redux中間件原理
- 7-31 串講react-router知識點
- 7-32 React使用-考點總結
- 第08章 React 原理
- 8-1 React原理-考點串講
- 8-2 再次回顧不可變值
- 8-3 vdom和diff是實現React的核心技術
- 8-4 JSX本質是什么
- 8-5 說一下React的合成事件機制
- 8-6 說一下React的batchUpdate機制
- 8-7 簡述React事務機制
- 8-8 說一下React組件渲染和更新的過程
- 8-9 React-fiber如何優化性能
- 第09章 React 面試真題演練
- 9-1 React真題演練-1-組件之間如何通訊
- 9-2 React真題演練-2-ajax應該放在哪個生命周期
- 9-3 React真題演練-3-組件公共邏輯如何抽離
- 9-4 React真題演練-4-React常見性能優化方式
- 9-5 React真題演練-5-React和Vue的區別
- 第10章 webpack 和 babel
- 10-1 webpack考點梳理
- 10-2 webpack基本配置串講(上)
- 10-3 webpack基本配置串講(下)
- 10-4 webpack如何配置多入口
- 10-5 webpack如何抽離壓縮css文件
- 10-6 webpack如何抽離公共代碼和第三方代碼
- 10-7 webpack如何實現異步加載JS
- 10-8 module chunk bundle 的區別
- 10-9 webpack優化構建速度-知識點串講
- 10-11 happyPack是什么
- 10-12 webpack如何配置熱更新
- 10-13 何時使用DllPlugin
- 10-14 webpack優化構建速度-考點總結和復習
- 10-15 webpack優化產出代碼-考點串講
- 10-16 什么是Tree-Shaking
- 10-17 ES Module 和 Commonjs 的區別
- 10-18 什么是Scope Hostin
- 10-19 babel基本概念串講
- 10-20 babel-polyfill是什么
- 10-21 babel-polyfill如何按需引入
- 10-22 babel-runtime是什么
- 10-23 webpack考點總結和復習
- 10-24 webpack面試真題-前端代碼為何要打包
- 10-25 webpack面試真題-為何Proxy不能被Polyfill
- 10-26 webpack面試真題-常見性能優化方法