这是我参与「第五届青训营 」伴学笔记创作活动的第4天
一、TypeScript 是什么
TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。 TypeScript 提供最新的和不断发展的 JavaScript 特性,包括那些来自 2015 年的 ECMAScript 和未来的提案中的特性,比如异步功能和 Decorators,以帮助建立健壮的组件。
1.1 TypeScript 与 JavaScript 的区别
1.2 获取 TypeScript
命令行的 TypeScript 编译器可以使用 Node.js 包来安装。
$ npm install -g typescript
2.编译 TypeScript 文件
$ tsc helloworld.ts
#helloworld.ts => helloworld.js
当然,对于刚入门 TypeScript 的小伙伴,也可以不用安装 typescript,而是直接使用线上的 TypeScript Playground 来学习新的语法或新特性。
二、TypeScript 基础类型
2.1 Boolean 类型
let isDone: boolean = false;
// ES5:var isDone = false;
2.2 Number 类型
let count: number = 10;
// ES5:var count = 10;
String 类型
let name: string = "Semliker";
// ES5:var name = 'Semlinker';
2.4 Array 类型
let list: number[] = [1, 2, 3];
// ES5:var list = [1,2,3];
let list: Array<number> = [1, 2, 3]; // Array<number>泛型语法
// ES5:var list = [1,2,3];
对象类型
函数类型
函数重载
TypeScript 泛型
软件工程中,我们不仅要创建一致的定义良好的 API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
在像 C# 和 Java 这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。
设计泛型的关键目的是在成员之间提供有意义的约束,这些成员可以是:类的实例成员、类的方法、函数参数和函数返回值。
泛型(Generics)是允许同一个函数接受不同类型参数的一种模板。相比于使用 any 类型,使用泛型来创建可复用的组件要更好,因为泛型会保留参数类型。
泛型接口
interface GenericIdentityFn<T> {
(arg: T): T;
}
泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) {
return x + y;
};
泛型变量
对刚接触 TypeScript 泛型的小伙伴来说,看到 T 和 E,还有 K 和 V 这些泛型变量时,估计会一脸懵逼。其实这些大写字母并没有什么本质的区别,只不过是一个约定好的规范而已。也就是说使用大写字母 A-Z 定义的类型变量都属于泛型,把 T 换成 A,也是一样的。下面我们介绍一下一些常见泛型变量代表的意思:
- T(Type):表示一个 TypeScript 类型
- K(Key):表示对象中的键类型
- V(Value):表示对象中的值类型
- E(Element):表示元素类型
泛型工具类型
为了方便开发者 TypeScript 内置了一些常用的工具类型,比如 Partial、Required、Readonly、Record 和 ReturnType 等。出于篇幅考虑,这里我们只简单介绍 Partial 工具类型。不过在具体介绍之前,我们得先介绍一些相关的基础知识,方便读者自行学习其它的工具类型。
1.typeof
在 TypeScript 中,typeof 操作符可以用来获取一个变量声明或对象的类型。
interface Person {
name: string;
age: number;
}
const sem: Person = { name: 'semlinker', age: 30 };
type Sem= typeof sem; // -> Person
function toArray(x: number): Array<number> {
return [x];
}
type Func = typeof toArray; // -> (x: number) => number[]
123456789101112131415
2.keyof
keyof 操作符可以用来一个对象中的所有 key 值:
interface Person {
name: string;
age: number;
}
type K1 = keyof Person; // "name" | "age"
type K2 = keyof Person[]; // "length" | "toString" | "pop" | "push" | "concat" | "join"
type K3 = keyof { [x: string]: Person }; // string | number
12345678910
3.in
in 用来遍历枚举类型:
type Keys = "a" | "b" | "c"
type Obj = {
[p in Keys]: any
} // -> { a: any, b: any, c: any }
1234567
4.infer
在条件类型语句中,可以用 infer 声明一个类型变量并且对它进行使用。
type ReturnType<T> = T extends (
...args: any[]
) => infer R ? R : any;
12345
以上代码中 infer R 就是声明一个变量来承载传入函数签名的返回值类型,简单说就是用它取到函数返回值的类型方便之后使用。
5.extends
有时候我们定义的泛型不想过于灵活或者说想继承某些类等,可以通过 extends 关键字添加泛型约束。
interface ILengthwise {
length: number;
}
function loggingIdentity<T extends ILengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
12345678910
现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:
loggingIdentity(3); // Error, number doesn't have a .length property
123
这时我们需要传入符合约束类型的值,必须包含必须的属性:
loggingIdentity({length: 10, value: 3});