TypeScript 基础类型
自本节起,我们将开始接触 TypeScript 的类型系统,这也是 TypeScript 最为核心的部分。
本节介绍 TypeScript 中一些基础类型,有些特殊类型会在接下来进行单节描述。在进行变量声明时,需要注明其对应的类型,这个跟 JavaScript 的变量声明不同。在写 TypeScript 代码时,所有的变量都需要有类型,这个观点要深刻的烙印在心里。
TypeScript 中的类型有:
- 原始类型
- boolean
- number
- string
- void
- null
- undefined
- bigint
- symbol
- 元组 tuple
- 枚举 enum
- 任意 any
- unknown
- never
- 数组 Array
- 对象 object
最简单的数据类型就是 true / false 值:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">const</span> registered<span style="color:#999999">:</span> <span style="color:#36bcd6">boolean</span> <span style="color:#a67f59">=</span> <span style="color:#36bcd6">false</span>
<span style="color:#36bcd6">const</span> done<span style="color:#999999">:</span> <span style="color:#36bcd6">boolean</span> <span style="color:#a67f59">=</span> <span style="color:#f92672">Boolean</span><span style="color:#999999">(</span><span style="color:#ae81ff">0</span><span style="color:#999999">)</span>
</code></span></span>
变量声明语法:冒号
:
前面是变量名称,后面是变量类型。
二进制数、十进制数、十六进制数都可以用 number
类型来表示。
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">let</span> decLiteral<span style="color:#999999">:</span> <span style="color:#36bcd6">number</span> <span style="color:#a67f59">=</span> <span style="color:#ae81ff">6</span>
<span style="color:#36bcd6">let</span> goldenSection<span style="color:#999999">:</span> <span style="color:#36bcd6">number</span> <span style="color:#a67f59">=</span> <span style="color:#ae81ff">0.618</span>
<span style="color:#36bcd6">let</span> hexLiteral<span style="color:#999999">:</span> <span style="color:#36bcd6">number</span> <span style="color:#a67f59">=</span> <span style="color:#ae81ff">0xf00d</span>
<span style="color:#36bcd6">let</span> binaryLiteral<span style="color:#999999">:</span> <span style="color:#36bcd6">number</span> <span style="color:#a67f59">=</span> <span style="color:#ae81ff">0b1010</span>
<span style="color:#36bcd6">let</span> octalLiteral<span style="color:#999999">:</span> <span style="color:#36bcd6">number</span> <span style="color:#a67f59">=</span> <span style="color:#ae81ff">0o744</span>
<span style="color:#36bcd6">let</span> notANumber<span style="color:#999999">:</span> <span style="color:#36bcd6">number</span> <span style="color:#a67f59">=</span> <span style="color:#ae81ff">NaN</span>
</code></span></span>
双引号或者单引号表示字符串:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">let</span> protagonist<span style="color:#999999">:</span> <span style="color:#36bcd6">string</span> <span style="color:#a67f59">=</span> <span style="color:#78ab12">"Sherlock Holmes"</span>
<span style="color:#36bcd6">let</span> partner<span style="color:#999999">:</span> <span style="color:#36bcd6">string</span> <span style="color:#a67f59">=</span> <span style="color:#78ab12">'Dr. John Hamish Watson'</span>
</code></span></span>
使用模板字符串:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">let</span> protagonist<span style="color:#999999">:</span> <span style="color:#36bcd6">string</span> <span style="color:#a67f59">=</span> <span style="color:#78ab12">'Sherlock'</span>
<span style="color:#36bcd6">let</span> sentence<span style="color:#999999">:</span> <span style="color:#36bcd6">string</span> <span style="color:#a67f59">=</span> <span style="color:#78ab12">`华生是</span><span style="color:#999999">${</span>protagonist<span style="color:#999999">}</span><span style="color:#78ab12">的朋友、助手和室友。`</span>
</code></span></span>
模板字符串使用反引号来代替普通字符串中的用双引号和单引号。模板字符串可以包含特定语法 ${expression}
的占位符,占位符内可以写变量名,模板字符串会进行变量值的解析。
当一个函数没有返回值时,可以将其返回值类型定义为 void:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">function</span> <span style="color:#f92672">doNothing</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">:</span> <span style="color:#36bcd6">void</span> <span style="color:#999999">{</span>
<span style="color:#36bcd6">let</span> a <span style="color:#a67f59">=</span> <span style="color:#ae81ff">10</span>
<span style="color:#999999">}</span>
</code></span></span>
声明一个 void
类型的变量没有什么用,因为你只能将它赋值为 undefined
和 null
:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">let</span> nothing<span style="color:#999999">:</span> <span style="color:#36bcd6">void</span> <span style="color:#a67f59">=</span> undefined
</code></span></span>
undefined
和 null
是所有类型的子类型。
一般项目是默认开启 --strictNullChecks
检测的(这句话不明白是什么意思),如果你将 tsconfig.json
中 strictNullChecks
选项设置为 false
,下面这种操作不会报错,不过尽量不要这么做:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">let</span> num<span style="color:#999999">:</span> <span style="color:#36bcd6">number</span> <span style="color:#a67f59">=</span> undefined
<span style="color:#36bcd6">let</span> list<span style="color:#999999">:</span> <span style="color:#36bcd6">number</span><span style="color:#999999">[</span><span style="color:#999999">]</span> <span style="color:#a67f59">=</span> undefined
<span style="color:#36bcd6">let</span> name<span style="color:#999999">:</span> <span style="color:#36bcd6">string</span> <span style="color:#a67f59">=</span> undefined
</code></span></span>
数组类型有两种表示方法,第一种在元素类型后接上 []
,表示由此类型元素组成的一个数组:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">let</span> list<span style="color:#999999">:</span> <span style="color:#36bcd6">number</span><span style="color:#999999">[</span><span style="color:#999999">]</span> <span style="color:#a67f59">=</span> <span style="color:#999999">[</span><span style="color:#ae81ff">1</span><span style="color:#999999">,</span> <span style="color:#ae81ff">2</span><span style="color:#999999">,</span> <span style="color:#ae81ff">3</span><span style="color:#999999">]</span>
<span style="color:#36bcd6">let</span> names<span style="color:#999999">:</span> <span style="color:#36bcd6">string</span><span style="color:#999999">[</span><span style="color:#999999">]</span> <span style="color:#a67f59">=</span> <span style="color:#999999">[</span><span style="color:#78ab12">'Sherlock'</span><span style="color:#999999">,</span> <span style="color:#78ab12">'Watson'</span><span style="color:#999999">,</span> <span style="color:#78ab12">'Mrs. Hudson'</span><span style="color:#999999">]</span>
</code></span></span>
另一种方式是使用数组泛型(泛型后续会单独介绍),Array<元素类型>
:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">let</span> list<span style="color:#999999">:</span> <span style="color:#36bcd6">Array</span><span style="color:#a67f59"><</span><span style="color:#36bcd6">number</span><span style="color:#a67f59">></span> <span style="color:#a67f59">=</span> <span style="color:#999999">[</span><span style="color:#ae81ff">1</span><span style="color:#999999">,</span> <span style="color:#ae81ff">2</span><span style="color:#999999">,</span> <span style="color:#ae81ff">3</span><span style="color:#999999">]</span>
<span style="color:#36bcd6">let</span> names<span style="color:#999999">:</span> <span style="color:#36bcd6">Array</span><span style="color:#a67f59"><</span><span style="color:#36bcd6">string</span><span style="color:#a67f59">></span> <span style="color:#a67f59">=</span> <span style="color:#999999">[</span><span style="color:#78ab12">'Sherlock'</span><span style="color:#999999">,</span> <span style="color:#78ab12">'Watson'</span><span style="color:#999999">,</span> <span style="color:#78ab12">'Mrs. Hudson'</span><span style="color:#999999">]</span>
</code></span></span>
混合各种元素类型:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">let</span> list<span style="color:#999999">:</span> <span style="color:#36bcd6">any</span><span style="color:#999999">[</span><span style="color:#999999">]</span> <span style="color:#a67f59">=</span> <span style="color:#999999">[</span><span style="color:#78ab12">'Sherlock'</span><span style="color:#999999">,</span> <span style="color:#ae81ff">1887</span><span style="color:#999999">]</span>
</code></span></span>
推荐使用第一种数组类型的表示方法,书写比较简洁直观。
有时候接收来自用户的输入,我们是不能确定其变量类型的。这种情况下,我们不希望类型检查器对这些值进行检查,而是直接让它们通过编译阶段的检查,此时可以使用 any
:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">let</span> input<span style="color:#999999">:</span> <span style="color:#36bcd6">any</span> <span style="color:#a67f59">=</span> <span style="color:#78ab12">'nothing'</span>
input <span style="color:#a67f59">=</span> <span style="color:#ae81ff">0</span> <span style="color:#708090">// ok</span>
input <span style="color:#a67f59">=</span> <span style="color:#36bcd6">true</span> <span style="color:#708090">// ok</span>
input <span style="color:#a67f59">=</span> <span style="color:#999999">[</span><span style="color:#999999">]</span> <span style="color:#708090">// ok</span>
input <span style="color:#a67f59">=</span> <span style="color:#36bcd6">null</span> <span style="color:#708090">// ok</span>
input <span style="color:#a67f59">=</span> <span style="color:#f92672">Symbol</span><span style="color:#999999">(</span><span style="color:#78ab12">'any'</span><span style="color:#999999">)</span> <span style="color:#708090">// ok</span>
</code></span></span>
如果一个数据是 any 类型,那么可以访问它的任意属性,即使这个属性不存在:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">let</span> anything<span style="color:#999999">:</span> <span style="color:#36bcd6">any</span> <span style="color:#a67f59">=</span> <span style="color:#ae81ff">10</span>
anything<span style="color:#999999">.</span><span style="color:#f92672">eat</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#708090">// ok</span>
anything<span style="color:#999999">.</span>name <span style="color:#708090">// ok</span>
anything<span style="color:#999999">[</span><span style="color:#ae81ff">0</span><span style="color:#999999">]</span> <span style="color:#708090">// ok</span>
<span style="color:#36bcd6">new</span> anything<span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#708090">// ok</span>
<span style="color:#f92672">anything</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#708090">// ok</span>
</code></span></span>
从上面的例子中可以看到,any 类型几乎可以做任何操作,这样很容易编写类型正确但是执行异常的代码。我们使用 TypeScript 就是为了代码的健壮性,所以要尽量减少 any 的使用。
object
表示非原始类型(non-primitive type):
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">let</span> obj<span style="color:#999999">:</span> object
<span style="color:#708090">// 枚举类型</span>
<span style="color:#36bcd6">enum</span> TokenType <span style="color:#999999">{</span>
ACCESS <span style="color:#a67f59">=</span> <span style="color:#78ab12">'accessToken'</span><span style="color:#999999">,</span>
REFRESH <span style="color:#a67f59">=</span> <span style="color:#78ab12">'refreshToken'</span>
<span style="color:#999999">}</span>
obj <span style="color:#a67f59">=</span> TokenType
obj <span style="color:#a67f59">=</span> <span style="color:#999999">[</span><span style="color:#ae81ff">1</span><span style="color:#999999">,</span> <span style="color:#ae81ff">2</span><span style="color:#999999">,</span> <span style="color:#ae81ff">3</span><span style="color:#999999">]</span>
obj <span style="color:#a67f59">=</span> <span style="color:#999999">[</span><span style="color:#ae81ff">1</span><span style="color:#999999">,</span> <span style="color:#78ab12">'string'</span><span style="color:#999999">]</span> <span style="color:#708090">// 元组类型</span>
obj <span style="color:#a67f59">=</span> <span style="color:#999999">{</span> a<span style="color:#999999">:</span> <span style="color:#ae81ff">1</span> <span style="color:#999999">}</span>
</code></span></span>
可以看到枚举、数组、元组和普通对象都是 object
类型。
- TypeScript 中描述类型要用
小写
,比如 boolean、number、string等; - 大写开头的如 Boolean、Number、String 代表的是 JavaScript 的构造函数:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-ts"><span style="color:#36bcd6">let</span> a <span style="color:#a67f59">=</span> <span style="color:#36bcd6">new</span> Number<span style="color:#999999">(</span><span style="color:#78ab12">'10'</span><span style="color:#999999">)</span> <span style="color:#708090">// a === 10 为 false</span>
<span style="color:#36bcd6">let</span> b <span style="color:#a67f59">=</span> <span style="color:#f92672">Number</span><span style="color:#999999">(</span><span style="color:#78ab12">'10'</span><span style="color:#999999">)</span> <span style="color:#708090">// b === 10 为 true</span>
a <span style="color:#36bcd6">instanceof</span> Number <span style="color:#708090">// true</span>
b <span style="color:#36bcd6">instanceof</span> Number <span style="color:#708090">// false</span>
</code></span></span>
代码解释:
第 1 行,通过 new Number('10')
得到的是一个构造函数,本质是一个对象。
第 2 行,Number('10')
与 10
都是声明一个数字 10 的方法,本质就是一个数字。
第 4 - 5 行,instanceof
运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。a
是一个对象,它的 __proto__
属性指向该对象的构造函数的原型对象 Number
,所以为 true
。b
是一个数字,所以为 false
。
__proto__
是非标准属性,你也可以使用 Object.getPrototypeOf()
方法来访问一个对象的原型:
<span style="color:#1c1f21"><span style="color:#333333"><code class="language-js">a<span style="color:#999999">.</span>__proto__ <span style="color:#a67f59">===</span> Object<span style="color:#999999">.</span><span style="color:#f92672">getPrototypeOf</span><span style="color:#999999">(</span>a<span style="color:#999999">)</span> <span style="color:#708090">// true</span>
</code></span></span>
本小节介绍了 TypeScript 一些基本类型,需要记住的是:
- TypeScript 中描述类型要用
小写
。 - 不要滥用
any
!