目录
- 前言
- 1、基元类型
- 2、数组
- 3、any
- 4、函数
- 5、对象
- 6、unknown
前言
在学习TypeScript之前我们需要先全局安装tsc
TypeScript 编译器。
npm
在项目根目录下运行:
tsc -init
此时项目根目录下会生成一个配置文件 tsconfig.json
,这里给出我使用的配置:
{
"compilerOptions": {
/* TS编译成JS的版本*/
"target": "es6",
/* 入口文件:指定源文件中的根文件夹。 */
"rootDir": "./src",
/* 编译出口文件:指定输出文件夹。 */
"outDir": "./dist",
/* 严格模式 */
"strict": true,
}
}
注意:我们实用TypeScript
的目的就是检验代码并纠错,尽量使自己的代码变得足够规范,所以建议应始终使用"strict": true
1、基元类型
JavaScript
有三个非常常用的类型: string
, number
,和boolean
。
它们在 TypeScript
中都有对应的类型,并且这些名称与在 JavaScript
应用typeof
返回的类型的名称相同:
-
string
表示字符串值,如"Hello, world"
-
number
表示数字值,如 42 。JavaScript
没有一个特殊的整数运行时值,所以没有等价于int
或float
类型, 一切都只是number
-
boolean
只有两个值true
和false
类型名称String
, Number
, 和Boolean
(以大写字母开头)是合法的,但指的是一些很少出现在
代码中的特殊内置类型。对于类型,始终使用string
, number
, 或boolean
。
在TypeScript
中,当你使用const
, var
, 或let
时可以直接在变量后加上类型注释: type
就可以显式指定变量的类型为type
:
var str: string = "hello,world";
const num: number = 42;
let boo: boolean = true;
但是,在大多数情况下,这不是必需的。只要有可能,TypeScript
就会尝试自动推断代码中的类型。例如,变量的类型是根据其初始化器的类型推断出来的:
// 不需要类型定义--“myName”自动推断为类型“string”
let myName = "AiLjx";
对于已经声明类型的变量,对其赋值时只能赋予其相同类型的数据,否者TypeScript
将会抛出错误:
2、数组
指定数组的类型可以使用ItemType[]
或者Array<ItemType>
,ItemType
指数组元素的类型,
Array<ItemType>
声明类型的方式使用了TypeScript
的泛型语法,对于泛型,之后我会出单独的一篇博文对其详细的介绍
const arr1:number[]=[1,2,3]
const arr2:string[]=['1','2','3']
同样的,对已经指定类型的数组赋不同类型的值,或向其添加不同类型的数据时,TypeScript将会抛出错误:
3、any
TypeScript
还有一个特殊类型 any
,当你不希望某个特定值导致类型检查错误时,可以使用它。
当一个值的类型是any
时,可以访问它的任何属性,将它分配给任何类型的值,或者几乎任何其他语法上的东西都合法的:
src/01-type.ts
:
let obj: any = { x: 0 };
// 以下代码行都不会抛出编译器错误。
// 使用'any'将禁用所有进一步的类型检查
obj.foo();
obj();
obj.bar = 100;
obj = "hello";
const n: number = obj;
但在运行环境下执行代码可能是错误的:
进入到 dist
目录中,在 node
环境里运行代码,果然报错了。
当你不想写出长类型只是为了让 TypeScript
相信特定的代码行没问题时, any
类型很有用。
但万万不可大量使用any
类型,因为any
没有进行类型检查,使用它就相当于在使用原生JS
,失去了TS
的意义!!!
4、函数
TypeScript
允许您指定函数的输入和输出值的类型。
- 参数类型注释
声明函数时,可以在每个参数后添加类型注解,以声明函数接受的参数类型。参数类型注释位于参数名称之后:
// 参数类型定义
function getName(name: string) {
console.log("Hello, " + name);
}
这里指定了getName
函数接收一个string
类型的参数,当参数类型不匹配时将抛出错误:
即使您的参数上没有类型注释,TypeScript
仍会检查您是否传递了正确数量的参数!
- 返回类型注释
返回类型注释出现在参数列表之后,其指定了函数返回值的类型:
function getName(name: string): string {
console.log("Hello, " + name);
return "Hello, " + name;
}
这里对getName
函数指定了其返回值是string
类型,当函数无返回值或返回值不是string
类型时将抛出错误:
与变量类型注释非常相似,通常不需要返回类型注释,因为 TypeScript
会根据其return
语句推断函数的返回类型。上面例子中的类型注释不会改变任何东西。某些代码库会出于文档目的明确指定返回类型,以防止意外更改或仅出于个人偏好。
- 匿名函数
匿名函数与函数声明有点不同。当一个函数出现在 TypeScript
可以确定它将如何被调用的地方时,该函数的参数会自动指定类型。
即使参数s
没有类型注释,TypeScript
也会使用forEach
函数的类型,以及数组的推断类型来确定s
的类型。这个过程称为上下文类型,因为函数发生在其中的上下文通知它应该具有什么类型。
与推理规则类似,你不需要明确了解这是如何发生的,但了解它的机制确实可以帮助你注意何时不需要类型注释。
从这里我们就能看出TypeScript
的强大之处,它不仅能够自动推断类型并发现错误,还能提示你错误的地方,以及修复建议,配合VS code
编译器还能实现快速修复:
5、对象
除了string
, number
, boolean
类型(又称基元类型)外,你将遇到的最常见的类型是对象类型。
这指的是任何带有属性的 JavaScript
值,几乎是所有属性!要定义对象类型,我们只需列出其属性及其类型。
let obj: { x: number; y: number } = { x: 1, y: 2 };
对于指定类型的对象其值不符合指定的类型时抛出错误:
- 可选属性
在指定的类型属性名后加上一个?
,可以指定该属性为可选属性:
let obj2: { x?: number; y: number } = {
y: 2, // x 是可选属性,对象内不含x属性时将不再抛出错误
};
不能直接对可选属性进行操作,不然就会抛出错误:
这很好理解,因为可选属性没有限制用户必传,如果访问一个不存在的属性,将获得值undefined
,此时对其操作TypeScript
就会抛出错误提醒你。
正确的做法:
function ObjFn(obj: { x?: number; y: number }) {
console.log(obj.y++);
if (obj.x) { // 先判断可选属性是否存在
console.log(obj.x++);
}
}
6、unknown
与 any
类型类似,可以设置任何的类型值,随后可以更改类型,但unknown
要比any
更加安全,看个例子:
let a: any = "Ailjx";
a = [];
a.push("0");
上面代码在编译与运行时都是正常的,但是当我们手误写错了push
方法后你就会发现问题所在:
let a: any = "Ailjx";
a = [];
a.psh("0");
这段代码在编译时不会报错,只会在运行时报错,这就失去了TypeScript
在编译时检查错误的功能,在项目比较大时,参与的人多时,就很难避免这样类似的问题,因此unknown
类型出现了:
虽然我们将其类型更改为数组类型,但是编译器认为其依旧是unknown
类型,该类型没有push
方法,就会报错,除非我们先判断类型:
let a: unknown = "Ailjx";
a = [];
if (a instanceof Array) {
a.push("0");
}
这样代码就没问题了,这时如果你push方法写错了,编译器就会报错提示你了:
虽然有些麻烦,但是相比 any
类型说,更加安全,在代码编译期间,就能帮我们发现由于类型造成的问题,因此在大多的场景,建议使用 unknown
类型替代 any
。