森林物语 發表於 2019-9-14 15:12:00

TypeScript类型检查机制

<h2>类型推断</h2>
<p><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">指不需要指定变量的类型,TS编译器可以根据某些规则自动推断出类型。</span></p>
<p><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">什么时候会有类型推断?</span></p>
<ul>
<li><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">声明变量时没有指定类型</span></li>
<li><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">函数默认参数</span></li>
<li><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">函数返回值</span></li>
<li><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">......</span></li>
</ul>
<div class="cnblogs_Highlighter">
<pre class="brush:javascript;gutter:true;">let a; // 这时自动推断为any类型
let b = 1; // 推断为number类型
let c = []; // 推断为由any类型构成的数组
let d = (x=1) =&gt; x+1; // 函数传参时,默认参数被推断成number类型,返回值也会被推断
let e = ; // 推断出兼容所有数据的类型:number和null的联合类型

有时候TS类型推断不符合我们的预期,我们应该比编译器更有信心它应该是什么类型,类型断言就允许我们覆盖TS的推论。
interface Foo{
   bar: number
}
let foo: Foo = {} as Foo; // 如果一个对象按照接口的约定,需要有很多的属性和方法,难以在声明的时候定义完全。这时候可以用断言
foo.bar = 1; // 具体的定义在这里</pre>
</div>
<p><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">注意:类型断言不能乱用,要对上下文环境有充足的预判,没有任何根据的断言会带来安全隐患!</span></p>
<h2>类型兼容</h2>
<p><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">TS允许类型相互兼容的变量(函数、类等结构)相互赋值。</span></p>
<p><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">当一个类型Y可以被赋值给另一个类型X时,就认为类型X兼容Y,X为目标类型,Y为源类型。</span></p>
<p><strong><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">兼容规则:</span></strong></p>
<ul>
<li><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">结构之间兼容:成员少的兼容成员多的</span></li>
<li><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">函数之间兼容:参数多的兼容参数少的</span></li>
</ul>
<h3><strong><span style="font-family: &quot;Microsoft YaHei&quot;">接口兼容性</span></strong></h3>
<div class="cnblogs_Highlighter">
<pre class="brush:javascript;gutter:true;">interface X {
   a: any;
   b: any;
}
interface Y {
   a: any;
   b: any;
   c: any;
}
let x: X = {a:1,b:2};
let y: Y = {a:1,b:2,c:3};
x = y; // x兼容y 成员少的会兼容成员多的</pre>
</div>
<h3><span style="font-family: &quot;Microsoft YaHei&quot;">函数兼容性</span></h3>
<div class="cnblogs_Highlighter">
<pre class="brush:javascript;gutter:true;">// 参数个数的兼容
type Handler = (a: number,b: number) =&gt; void;
function hof(handler: Handler) {
   return handler
}
let handler1 = (a:number) =&gt; {};
hof(handler1); // 一个参数可以兼容
let handler2 = (a: number,b: number,c: number) =&gt; {};
// hof(handler2); // 三个参数不被兼容

// 可选参数和剩余参数的兼容
let a1 = (p1: number, p2: number) =&gt; {};
let b1 = (p1?: number, p2?: number) =&gt; {};
let c1 = (...args: number[]) =&gt; {};
a1 = b1;
a1 = c1;
// b1 = a1; // 可选参数不能被兼容。需要将tsconfig.json中“strictFunctionTypes”置为false即可
// b1 = c1;
c1 = a1;
c1 = b1;</pre>
</div>
<h3><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">类的兼容性</span></h3>
<p><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">两个定义不同的类互不兼容,子类在继承父类后没有做改动,可以兼容父类。</span></p>
<h3><span style="font-family: &quot;Microsoft YaHei&quot;"><span style="font-size: 15px">泛型的兼容性</span></span></h3>
<p><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">两个定义完全一样的泛型函数相互兼容</span></p>
<h2>类型保护</h2>
<p><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">TypeScript能够在特定的区块中保证变量属于某种确定的类型。可以在此区块中放心地访问此类型的属性和方法。</span></p>
<p><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">比如,我们要判断一个对象是否含有某个方法</span></p>
<div class="cnblogs_Highlighter">
<pre class="brush:javascript;gutter:true;">interface OBJ {
   name: string,
   age: number,
   sex: boolean
}
let obj: OBJ = {
   name: "typescript",
   age: 10,
   sex: true,
};
if(obj.sex) // obj中有sex属性,所以OK
{
   console.log("has sex");
}
// if(obj.bac) {}// obj中没有bac属性,此处报错。</pre>
</div>
<p><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">我们有四种提供类型保护的方式:</span></p>
<ul>
<li><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">instanceof&nbsp; &nbsp; 用于判断一个实例是否属于某个类</span></li>
<li><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">in&nbsp; &nbsp; 判断一个属性/方法是否属于某个对象</span></li>
<li><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">typeof&nbsp; &nbsp; 用于判断基本类型</span></li>
<li><span style="font-family: &quot;Microsoft YaHei&quot;; font-size: 15px">类型保护函数&nbsp; &nbsp; 当判断逻辑复杂时,可以自定义判断函数</span></li>
</ul>
<div class="cnblogs_Highlighter">
<pre class="brush:javascript;gutter:true;">class Java {
   helloJava(){
      console.log("hello java");
   }
   java: any;
}
class JavaScript {
   hellloJavaScript(){
      console.log("hello javascript");
   }
   javascript: any;
}

// 类型保护函数注意参数类型 和 返回值类型 的关系
function isJava(lang: Java|JavaScript):lang is Java {
   return (lang as Java).helloJava !== undefined
}

function getLanguage(type: number,x: string|number|boolean) {
   let lang = type === 1 ? new Java() : new JavaScript();
   // instanceof 判断lang是否属于Java类
   if(lang instanceof Java)
   {
      lang.helloJava(); // 在这个区块中,能够保证lang一定是java的实例,调用自己的方法
   }else
   {
      lang.hellloJavaScript(); // 这个区块中,一定能够保证lang是JavaScript的实例
   }
   // in “helloJava”方法是否属于lang对象
   if("helloJava" in lang)
   {
      lang.java; // 在这个区块中能够保证,lang是java的实例
   }else
   {
      lang.javascript // 这个区块中能够保证lang是JavaScript的实例
   }
   // typeof 用于判断基本类型
   if(typeof x === "string")
   {
      x.length // 程序进入这个区块,能够保证x是string类型。可以调用字符串原生方法
   }else if(typeof x === "number")
   {
      x.toFixed(2); // 在这里能够调用数字的原生方法
   }else
   {
      x = !x;
   }
   // 类型保护函数 在定义的时候,注意返回值的类型和参数类型的关系
   if(isJava(lang))
   {
      lang.helloJava();
   }else
   {
      lang.hellloJavaScript();
   }
}
getLanguage(2,"str");</pre>
</div>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/V587Chinese/p/11474686.html
頁: [1]
查看完整版本: TypeScript类型检查机制