TypeScript 基础类型
一、TypeScript 是什么
TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。
TypeScript 提供最新的和不断发展的 JavaScript 特性,包括那些来自 2015 年的 ECMAScript 和未来的提案中的特性,比如异步功能和 Decorators,以帮助建立健壮的组件。
1.1 TypeScript 与 JavaScript 的区别
TypeScript | JavaScript |
JavaScript 的超集用于解决大型项目的代码复杂性 | 一种脚本语言,用于创建动态网页 |
可以在编译期间发现并纠正错误 | 作为一种解释型语言,只能在运行时发现错误 |
强类型,支持静态和动态类型 | 弱类型,没有静态类型选项 |
最终被编译成 JavaScript 代码,使浏览器可以理解 | 可以直接在浏览器中使用 |
支持模块、泛型和接口 | 不支持模块,泛型或接口 |
支持 ES3,ES4,ES5 和 ES6 等 | 不支持编译其他 ES3,ES4,ES5 或 ES6 功能 |
1.2 安装和编译TypeScript
// npm 安装
npm install -g typescript
// 创建 helloWorld.ts 文件
// 编译 helloWorld.ts 文件
tsc helloWorld.ts
// 运行后会生成 helloWorld.js 的js文件
1.3 vsCode自动编译TypeScript
a、 在终端打开ts项目
b、 运行命令 tsc --init 生成 tsconfig.json 配置文件
tsc --init
c.、找到outDir 配置 生成 编译文件的目录,列如 我的是生成 到 js 目录下
d、新建ts文件
e、点击终端 --> 运行任务 --> 选择 typescript --> 选择tsc监视
项目目录下 会自己生成 js 文件 和 编译的xxx.js 文件,编译 .ts 文件会在 js 目录下生成 对应的 js 文件。
二、TypeScript 基础类型
2.1 Boolean 类型
let bool: boolean = true
2.2 Number 类型
let num: number = 168
2.3 String 类型
// 用 单引号 ' 或 双引号 " 表示字符串
let name: String = '坤坤'
name = "hello"
// 还可以使用模板语法
let age: number = 10
let name: String = `坤坤, ${age}岁`
2.4 Array 类型
// 1. 直接在类型后面接上[], 表示这个类型的数组
let arrNum: number[] = [1, 2, 3]
let arrStr: string[] = ['a', 'b', 'c']
// 2. 使用数组泛型 Array<元素类型>
let arr: Array<number> = [1, 2, 3]
// 3. 使用元组 Tuple 表示一个已知元素数量和类型的数组
let arr: [string, number] = ['坤坤', 10] // true
let arr: [string, number] = [10, 10] // false
2.5 Enum 类型
使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字的和基于字符串的枚举。
数字枚举
enum color {
red,
green,
orange
}
// 默认初始化下标 red = 0 且自动增长 例如: green = 1
// 你也可以自己定义下标 例:
enum direction {
up = 1,
down = 3,
left,
right
}
// 使用
let apple: String = color[0]
let grass: color = color.green
console.log(apple) // red
console.log(grass) // 0
// 这里我们可以看出,数字枚举是相互映射的
编译后的es5如下
"use strict";
var color;
(function (color) {
color[color["red"] = 0] = "red";
color[color["green"] = 1] = "green";
color[color["orange"] = 2] = "orange";
})(color || (color = {}));
字符串枚举
在 TypeScript 2.4 版本,允许我们使用字符串枚举。在一个字符串枚举里,每个成员都必须用字符串字面量,或另外一个字符串枚举成员进行初始化。
enum direction {
up = 'up',
down = 'down',
left = 'left'
}
// 使用
let path: direction = direction.up
let pathTwo: direction = direction['up']
异构枚举
通俗来讲就是数字和字符拆枚举的组合
enum Enum {
age = 1,
color = 'red'
}
2.6 Any 类型
在 TypeScript 中,任何类型都可以被归为 any 类型。这让 any 类型成为了类型系统的顶级类型(也被称作全局超级类型)。
any类型是十分有用的,它允许你在编译时可选择地包含或移除类型检查。
let people: any = '坤坤' // true
people = 10 // true
people = false
let value: any
value.foo.bar; // true
value.trim(); // true
value(); // true
new value(); // true
value[0][1]; // true
2.7 Void 类型
某种程度上来说,void类型像是与any类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void
function warnUser(): void {
console.log("This is my warning message")
}
声明一个void类型的变量没有什么大用,因为你只能为它赋予undefined和null
let unusable: void = undefined
2.8 Null 和 Undefined 类型
TypeScript 里,undefined 和 null 两者有各自的类型分别为 undefined 和 null。
let u: undefined = undefined
let n: null = null
复制代码默认情况下 null 和 undefined 是所有类型的子类型。 就是说你可以把 null 和 undefined 赋值给 number 类型的变量。然而,如果你指定了–strictNullChecks 标记,null 和 undefined 只能赋值给 void 和它们各自的类型。
2.9 Never 类型
never 类型表示的是那些永不存在的值的类型。 例如,never 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型。
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message)
}
function infiniteLoop(): never {
while (true) {}
}
复制代码在 TypeScript 中,可以利用 never 类型的特性来实现全面性检查,具体示例如下:
type Foo = string | number;
function uniteNever(foo: Foo) {
if (typeof foo === "string") {
// 这里 foo 被收窄为 string 类型
} else if (typeof foo === "number") {
// 这里 foo 被收窄为 number 类型
} else {
// foo 在这里是 never
const check: never = foo
}
}
复制代码注意在 else 分支里面,我们把收窄为 never 的 foo 赋值给一个显示声明的 never 变量。如果一切逻辑正确,那么这里应该能够编译通过。但是假如后来有一天你的同事修改了 Foo 的类型:
type Foo = string | number | boolean
复制代码然而他忘记同时修改 uniteNever 方法中的控制流程,这时候 else 分支的 foo 类型会被收窄为 boolean 类型,导致无法赋值给 never 类型,这时就会产生一个编译错误。通过这个方式,我们可以确保 uniteNever 方法总是穷尽了 Foo 的所有可能类型。 通过这个示例,我们可以得出一个结论:使用 never 避免出现新增了联合类型没有对应的实现,目的就是写出类型绝对安全的代码。
2.10 Object 类型
object表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型。
使用object类型,就可以更好的表示像Object.create这样的API。例如:
declare function create(o: object | null): void
create({ prop: 0 }); // OK
create(null); // OK
create(42) // Error
create("string") // Error
create(false) // Error
create(undefined) // Error
2.11 Unknown 类型
就像所有类型都可以赋值给 any,所有类型也都可以赋值给 unknown。这使得 unknown 成为 TypeScript 类型系统的另一种顶级类型(另一种是 any)。下面我们来看一下 unknown 类型的使用示例:
let value: unknown;
value = true; // OK
value = 42; // OK
value = "Hello World"; // OK
value = []; // OK
value = {}; // OK
value = Math.random; // OK
value = null; // OK
value = undefined; // OK
value = new TypeError(); // OK
value = Symbol("type"); // OK
复制代码对 value 变量的所有赋值都被认为是类型正确的。但是,当我们尝试将类型为 unknown 的值赋值给其他类型的变量时会发生什么?
let value: unknown;
let value1: unknown = value; // OK
let value2: any = value; // OK
let value3: boolean = value; // Error
let value4: number = value; // Error
let value5: string = value; // Error
let value6: object = value; // Error
let value7: any[] = value; // Error
let value8: Function = value; // Error
复制代码unknown 类型只能被赋值给 any 类型和 unknown 类型本身。直观地说,这是有道理的:只有能够保存任意类型值的容器才能保存 unknown 类型的值。毕竟我们不知道变量 value 中存储了什么类型的值。
现在让我们看看当我们尝试对类型为 unknown 的值执行操作时会发生什么。
let value: unknown;
value.foo.bar; // Error
value.trim(); // Error
value(); // Error
new value(); // Error
value[0][1]; // Error
复制代码将 value 变量类型设置为 unknown 后,这些操作都不再被认为是类型正确的。通过将 any 类型改变为 unknown 类型,我们已将允许所有更改的默认设置,更改为禁止任何更改。
TypeScript 类型断言
有时候你会遇到这样的情况,你会比TypeScript更了解某个值的详细信息。 通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript会假设你,程序员,已经进行了必须的检查。
类型断言有两种形式。 其一是“尖括号”语法:
let someValue: any = "this is a string"
let strLength: number = (<string>someValue).length
另一个为as语法:
let someValue: any = "this is a string"
let strLength: number = (someValue as string).length
两种形式是等价的。 至于使用哪个大多数情况下是凭个人喜好;然而,当你在TypeScript里使用JSX时,只有 as语法断言是被允许的。
好了,就到这了, 猛男下班 又是划水的一天