前端学习之旅 —— TypeScript 学习笔记(1)

151 阅读3分钟

什么是TypeScript?

TypeScript 是具有静态类型的 JavaScript扩展。

在TypeScript中,可以定义基础类型,甚至接口,使用类型别名、泛型、类型推导等语言特性。这些特性在工程项目实战中有多方面的好处,让IDE可以提供更多编程提示,在编程时也能注意到变量的类型约束,在合作开发时有更好的可读性和可维护性。

TypeScript 的类型

基础类型

  • string,字符串
let str: string = "hello world!";
  • number,数字
let num: number = 1;
  • boolean,布尔值
let isFinished: boolean = true;
  • Array,数组
let ids: Array<string> = ["111", "222", "333"];
// 这样的写法是一样的:
let ids: string[] = ["111", "222", "333"];
  • any,任意类型,在定义后,可以将any变量赋值为任意类型的其他值,这都是合法的
let obj: any = 1;
obj = "hello";

适当使用any,可以让编译器适当跳过一些自己不知道或者不确定变量类型的类型检查。

但是注意,不要滥用any,如果你几乎将所有的变量定义成any类型,其实和写JavaScript无异

  • Tuple,元组,可以拿React中的useState这个hook的返回值类比,就很好理解了;很显然你给每个数组元素都定义了类型,因此元组是个定长的数组
let versionInfo: [string, string] = ["typescript", "3.1"];
  • undefined & null
let name: undefined = undefined;
let age: null = null;
  • Enum,枚举,在项目中很常用的一个概念

比如这段代码,判断红灯停止运行的逻辑

// 1表示红灯,2表示绿灯,3表示黄灯
let current;
if (current === 1) {
    stop();
}

适当地使用枚举修改一下这段代码,增加了其可读性

enum Color {
    Red, Green, Yellow
}

let current: Color = getColor();
if (current === Color.Red) {
    stop();
}
  • Void,表示函数没有任何返回值
function printLog(log: string): void {
    console.log(log);
}
// 类似于kotlin的函数定义方式,将返回值类型在函数后,使用冒号标出
  • Never,表示永不存在的值的类型,是所有类型的子类型,所以never可以赋值给所有类型,但是,反过来,所有类型都不可以赋值给never类型!any也不可以

怎么理解这个永不存在呢?异常或者不可达

// 异常
function error(message: string): never {
    throw new Error(message);
}

// 异常
function fail() {
    return error("failed!");
}

// 函数永远也不会到达结束点
function infiniteLoop(): never {
    while (true) {}
}

接口

interface, 是很多编程语言都有的一个概念,如Java,他们通常用来定义抽象方法;在TypeScript中,接口可以指定对象的属性、方法和类型,也可以扩展

interface Student {
    id: string;
    name?: string; // 可选属性
    readonly majority: string; // 只读属性
}

// 扩展
interface StudentInCS extends Student {
    programingLanguage: string;
}

当然,interface也可以像其他编程语言一样来定义函数类型

interface PrintLog {
    (message: string): void;
}
const printLog: PrintLog = (message) => console.log(message);

联合类型&交叉类型

  • 联合类型可以理解为“”,是这些类型中的其中一种
type ReturnValue = string | number;
let value = "ok";
value = 1;
  • 交叉类型可以理解为“”,对象需要包含所有的属性
type Person = { name: string; age: number };
type Student = { school: string };
type Graduate = Person & Student;
const graduate: Graduate = {
    name: "pro",
    age: 24,
    school: "juejin"
}

泛型

泛型同样地在很多编程语言中有这一个类型,它将类型在定义时参数化,在实例化时再指明具体类型,支持泛型函数、泛型接口、泛型类

function identity<T>(arg: T): T {
  return arg;
}

interface GenericIdentityFn {
  <T>(arg: T): T;
}

class GenericClass<T> {
    value: T;
}

当然,也存在泛型约束,例如:

function identity<T extends { length: number }>(arg: T): T {
    console.log(arg.length);
    return arg;
}

identity(3); // error
identity({ length: 1, name: 'pro' }); // ok

这里约束了T必须包含length这个属性

刚开始创作,有写的不对,理解的不对的地方,希望指正!