TypeScript学习记录-入门概述、常用类型

106 阅读7分钟

概述

  • TypeScript(简称:TS)是 JavaScript 的超集(JS 有的 TS 都有)
  • TypeScript = Type + JavaScript(在 JS 基础之上,为 JS 添加了类型支持)
  • TypeScript 是微软开发的开源编程语言,可以在任何运行 JavaScript 的地方运行

需求

JS 代码中绝大部分错误都是类型错误(Uncaught TypeError)

编程语言的动静来区分:

  • TypeScript 属于静态类型的编程语言
    • 静态类型:编译期做类型检查
  • JS 属于动态类型的编程语言
    • 动态类型:执行期做类型检查

代码编译和代码执行的顺序:1 编译 2 执行

TS 可以提前到在编写代码的同时就发现代码中的错误

优势

  • 更早(写代码的同时)发现错误,减少找 Bug、改 Bug 时间,提升开发效率
  • 程序中任何位置的代码都有代码提示,随时随地的安全感,增强了开发体验
  • 强大的类型系统提升了代码的可维护性,使得重构代码更加容易
  • 支持最新的 ECMAScript 语法,优先体验最新的语法,让你走在前端技术的最前沿
  • TS 类型推断机制,不需要在代码中的每个地方都显示标注类型,让你在享受优势的同时,尽量降低了成本

擦除类型

实际上没有任何浏览器在未经修改的情况下运行 TypeScript,所以 TypeScript 需要编译器,通过某种方法来删除或转换任何特定于 TypeScript 的代码。大多数特定于 TypeScript 的代码都被删除了,同样地,类型注释也被完全删除了

降级

  • ECMAScript从新版本降到旧版本就叫降级,TypeScript 能够将代码从较新版本的 ECMAScript 重写为较旧的版本
  • 默认情况下,TypeScript 以 ES3 为目标
  • tsc --target es2015 hello.ts更改为以 ECMAScript 2015 为目标
  • 当前绝大多数浏览器都支持 ES2015,可以以es2015为标准,除非很是很古老的浏览器或者项目

严格性

  • CLI 中的 strict 标志或 tsconfig.json 中的 "strict": true 会将类型检查严格标志全部打开
  • noImplicitAny: 对任何类型隐式推断为 any 的变量触发错误
  • strictNullChecks:使处理 null 和 undefined 更加明确

使用

安装工具包

Node.js/浏览器,只认识 JS 代码,不认识 TS 代码。需要先将 TS 代码转化为 JS 代码,然后才能运行

安装

  • npm i -g typescript
  • tsc -v:查看版本
  • 使用:tsc hello.ts
  • 源文件有错误时,不再编译结果:tsc --noEmitOnError hello.ts

简化运行

使用 ts-node 包,直接在 Node.js 中执行 TS 代码

  • 安装:npm i -g ts-node
  • 使用:ts-node hello.ts

常用类型

TS 提供了 JS 的所有功能,并且额外的增加了:类型系统

  • 所有的 JS 代码都是 TS 代码
  • JS 有类型(比如,number/string 等),但是 JS 不会检查变量的类型是否发生变化,而 TS 会检查

TypeScript 类型系统的主要优势:可以显示标记出代码中的意外行为,从而降低了发生错误的可能性

TS 中的常用基础类型细分为两类:

  • JS 已有类型
    • 原始类型:number/string/boolean/null/undefined/symbol
    • 对象类型:object(包括,数组、对象、函数等对象)
  • TS 新增类型
    • 联合类型、自定义类型(类型别名)、接口、元组、字面量类型、枚举、void、any 等

类型声明

  • 语法:
let 变量: 类型;

let 变量: 类型 = 值;

function fn(参数: 类型, 参数: 类型): 类型{
  ...
}

原始类型(基本类型)

类型例子描述
number1, -33, 2.5任意数字
string'hi', "hi", hi任意字符串
booleantrue、false布尔值true或false
字面量其本身限制变量的值就是该字面量的值
any*任意类型
unknown*类型安全的any
void空值(undefined)没有值(或undefined)
never没有值不能是任何值

number

let a:number;

a = 10;

// a = 'hello';  报错

let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
let big: bigint = 100n;

boolean

let c:boolean = true;

// 赋值的时候就确定类型
let d = false;

// d = 123;   报错

string

let color: string = "blue";
color = 'red';

let fullName: string = `Bob Bobbington`;
let age: number = 37;
let sentence: string = `Hello, my name is ${fullName}.

I'll be ${age + 1} years old next month.`;

字面量

使用字面量去指定变量的类型,通过字面量可以确定变量的取值范围

let color: 'red' | 'blue' | 'black';
let num: 1 | 2 | 3 | 4 | 5;

let e:10;

e = 10;
// e = 11; 报错

字面推断

使用对象初始化变量时,TypeScript 假定该对象的属性可能会在以后更改值

declare function handleRequest(url: string, method: "GET" | "POST"): void;
 
const req = { url: "https://example.com", method: "GET" };

// 报错,` string `类型的参数不能赋值给` "GET" | "POST" `类型的参数
handleRequest(req.url, req.method);

在这里,req.method 被推断为 string,而不是 GET。因为可以在 req 的创建和 handleRequest 的调用之间评估代码,这可以将一个新的字符串(如 GUESS分配给 req.method),TypeScript 认为此代码有错误,有两种方法解决这个问题:

  • 通过在任一位置添加类型断言来更改推断:
// 方式一,让 req.method 始终具有字面量类型 "GET"
const req = { url: "https://example.com", method: "GET" as "GET" };
// 方式二,由于其他原因明确知道 req.method 的值为 "GET"
handleRequest(req.url, req.method as "GET");
  • 可以使用 as const 将整个对象转换为类型字面:
const req = { url: "https://example.com", method: "GET" } as const;
handleRequest(req.url, req.method);

as const 后缀的作用类似于 const,但用于类型系统,确保为所有属性分配字面类型,而不是更通用的版本,如 string 或 number

any

  • 表示任意类型,关闭类型检测
  • 如果不指定类型,ts自动判断类型为any
  • 编译器标志 noImplicitAny: 对任何类型隐式推断为 any 的变量触发错误
let g:any;
g=10;
g=true;
g="hello"

unknown

表示未知类型的值(类型安全的any,不能赋值给其他变量

let aa: unknown;
aa = 10;
aa = "hello";
aa = true;

let bb:string;

let cc:any;

// 如果一个变量的类型为any,这个变量可以赋值给其他任意变量
bb = cc;  // 正常
// 但类型为 unknown 不能赋值给其他任意变量
// bb = aa;  // 报错
if(typeof aa === "string"){
    bb = aa;
}


// 类型断言,用来告诉解析器变量的实际类型
bb = aa as string;
// 或者
bb = <string>aa;

void

表示,以函数为例,表示没有返回值的函数

function fn():void{
    // return;
    // return null;
    return undefined;
    // return 123;  报错
}

never

表示永远不会返回结果,一般用于抛出异常的函数

function fn2():never{
    throw new Error("报错了!");
}

bigint

用于非常大的整数

const oneHundred: bigint = BigInt(100);
 
const anotherHundred: bigint = 100n;

symbol

全局唯一引用

const firstName = Symbol("name");
const secondName = Symbol("name");
 
if (firstName === secondName) {
This comparison appears to be unintentional because the types 'typeof firstName' and 'typeof secondName' have no overlap.
  // Can't ever happen
}

对象类型

object{name:'孙悟空'}任意的JS对象
array[1,2,3]任意JS数组
tuple[4,5]元素,TS新增类型,固定长度数组
enumenum{A, B}枚举,TS中新增类型

object

// object表示一个对象
let aaa:object;
aaa = {};
aaa = function(){}

// 设置函数结构的类型声明
let ddd:(a:number, b:number)=>number;
ddd = function(n1:number, n2:number):number{
    return n1 + n2;
}

array

let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];

// string[] 表示字符串数组
let eee:string[];
eee = ['a', 'b', 'c'];
// eee = ['1', 2, 3]  报错

let ggg:Array<number>;
ggg = [2, 3] 

tuple

元组:固定长度的数组

let h: [string, number];
h = ['hello', 123]

enum

枚举

// 定义一个枚举类
enum Gender{
    male = 0,
    female = 1
}

let i:{name:string, gender: Gender};
i = {
    name: 'dishitian',
    gender: Gender.male
}

console.log(i.gender === Gender.male);

--------------------------------------------

enum Color {
  Red,
  Green,
  Blue,
}
let c: Color = Color.Green;

enum Color {
  Red = 1,
  Green,
  Blue,
}
let c: Color = Color.Green;

enum Color {
  Red = 1,
  Green = 2,
  Blue = 4,
}
let c: Color = Color.Green;

函数

允许指定函数的输入和输出值的类型

function get(name: string): number {
  console.log(name);
  return 26;
}

// 返回 Promise 的函数
async function getFavoriteNumber(): Promise<number> {
  return 26;
}