# TypeScript 是什么

  • TypeScript 是由 Microsoft 开发的一种开源编程语言,它扩展了 JavaScript,增加了静态类型系统和类、接口等面向对象的特性。TypeScript 代码在编译时会被转换为纯 JavaScript 代码,可以在任何支持 JavaScript 的环境中运行。

# 环境安装

  • 需要先安装 nodejs
# 全局安装 typescript
npm install typescript -g
# 查询 typescript 版本
tsc -v
# 初始化 typescript 项目,执行命令后会在根目录下生成 tsconfig.json, 可以通过修改该文件设置编译器的各种规则,比如严格模式 strict 等
tsc --init
  • 创建 ts 文件,比如 index.ts ,然后编写测试代码
let str:string='Hello World';
console.log(str);
  • 编译后运行
# 监控目录下所有 ts 文件变化,如果文件内容改变会自动将其编译为 js 文件,ts 文件修改完以后直接执行 js 文件即可
tsc -w 
# 新建终端执行 js 文件测试效果
node index.js
  • 或者使用 ts-node 插件运行
# 安装 ts-node 插件
npm install ts-node -g
# 初始化 npm,执行后会生成 package.json
npm init -y
# 安装 TypeScript 的 nodejs 声明
npm install @types/node -D
# 运行 ts 文件
ts-node index.ts

# arguments 对象

  • arguments 对是一个类数组对象,作用域在方法内部时,包含了当前函数被调用时传入的所有参数,也可以转换为数值,使用 arguments 调试的时候很方便
function foo(...params: any[]) {
    console.log(arguments); //[Arguments] { '0': 123, '1': 'hello', '2': true }
    const args = Array.from(arguments); // 将 arguments 对象转换为数组
    console.log(args); // [ 123, 'hello', true ]
}
foo(123, "hello", true);

# Any 类型和 Unknown 类型

# 相同点

  • any 和 unknown 都是顶级类型,是 Object 类型的父类

# 不同点

  • unknown 只能赋值给自身或者 any
  • unknown 表示不确定类型的参数,不允许调用对象的任何属性和方法,否则会出现编译错误,可以只用于方法中的输入或输出,是安全型的 any

# Never 类型

  • 用于从来都不会返回值的函数 (比如死循环),或者无论如何都会抛出异常的函数
const loop = (): never => {
    while (true) { }
}
const error = (): never => {
    throw new Error();
}

# Object 和 object 类型

  • Object(大写)和 Java 和 C# 一样都包含了所有类型,可以存放任意值
  • object(小写)只能存放引用类型或者函数
let a1:Object = 123
let a2:Object = true
let a3:Object = '123'
let a4:Object = {}
let a5:Object = []
let a6:Object = ()=>123
let b1:object = 123   // 报错
let b2:object = true  // 报错
let b3:object = '123' // 报错
let b4:object = {}
let b5:object = []
let b6:object = ()=>123

# Interface

# 多个同名的 Interface 会进行合并

interface Person {
    name: string;
}
interface Person {
    age: number;
}
let p1: Person = {
    name: "111",
    age: 18
}

# 可空类型?和只读类型 readonly

interface Person {
    name: string;
    age?: number;// 可空类型
    readonly id:number// 只读
    readonly print:()=>{}// 只读
}
let p1: Person = {
    name: "111",
    id:1,
    print:()=>{return true}
}
p1.id=2;// 报错
p1.print=()=>{return false}; // 报错

# 继承 extends

interface ClassA {
    name: string;
}
interface ClassB {
    age: number;
    sex: boolean
}
// 可以继承多个
interface Person extends ClassA, ClassB {
    print: () => {};
}

# 接口定义函数

interface Show{
    (name:string,age:number):string
}
const fn:Show=(name:string,age:number)=>`${name}:${age}`
console.log(fn('张三',18));

# Interface 索引签名

  • 实现 Interface 的对象的属性数量必须与接口的属数量保持一致,如果只是用到 Interface 中的一小部分属性可以使用属性签名
interface Person{
    name:string,    // 只定义需要用到的属性
    age:number,     // 只定义需要用到的属性
    // 这里 propName 是可以任意取的名称,变量的名称是 string 类型,值类型是 any
    [propName:string]:any   // 其他属性定义为 any
}
let p1:Person={
    name:'111',
    age:18,
    sex:0
}
p1.address='2222';   // 可以动态添加更多的属性值
  • 也可以分开定义固定属性和动态属性
interface Product {
    name: string;
    price: number;
    stock: {
        [size: string]: number;
    };
    colors: {
        [color: string]: boolean;
    };
}
const hoodie: Product = {
    name: 'Hoodie',
    price: 50,
    stock: {
        'S': 5,
        'M': 8,
        'L': 3,
    },
    colors: {
        'Red': true,
        'Blue': false,
    },
};
console.log(hoodie.stock['S']);
console.log(hoodie.colors['Red']);

# 数组定义

// 常用定义
let arr1: number[] = [1, 2, 3, 4];
// 泛型定义
let arr2: Array<number> = [1, 2, 3, 4];
// 对象数组
interface Person {
    name: string
}
let arr3: Person[] = [{ name: '111' }];
let arr4: Array<Person> = [{ name: '222' }];
// 二维数组
let arr5:number[][]=[[1],[2],[3]];
let arr6:Array<Array<number>>=[[1],[2],[3]];
// 大杂烩数组
let arr7:any[]=[123,'abc',true];
let arr8:[number,string,boolean,{}]=[123,'abc',true,{name:'333'}]
// 剩余参数...args
function fn(...args:number[]){
    console.log(args);
    console.log(arguments);
}
fn(1,2,3,4,5);

# 函数定义

// 常用定义
function fn1(a: number, b: number): number {
    return a + b;
}
// 箭头函数
const fn2 = (a: number, b: number): number => {
    return a + b;
}
// 默认参数
const fn3 = (a: number = 1, b: number = 2): number => {
    return a + b;
}
// 可选参数 (可空参数)
const fn4 = (a: number, b?: number): number => {
    return a + (b ?? 0);
}
console.log(fn4(1));// 输出 1

# 函数重载

  • 函数重载有点复杂,不像 Java 或者 C# 等可以直接写同名的实现方法,还是少用为好
// 函数声明,不写也可以,写了以后 VSCode 可以显示有这些方法可以重载
function message(options: object): void;
function message(text: string, onClose?: Function): void;
function message(text: string, mode?: string, duration?: number): void;
function message(text: string, duration?: number, onClose?: Function): void;
// 函数实现
function message(
  param1: string | object,
  param2?: number | Function | string,
  param3?: Function | number
): string {
    if(typeof param1=='string') return param1;
    if(typeof param1=='object') return param1.toString();
    // 以此类推做业务处理...
    return '';
}
// 调用方式 1
message({
  mode: "mode",
  text: "msg",
  onClose: () => {},
  duration: 3000,
});
// 调用方式 2
message("msg");
message("msg", () => {});
message("msg", "mode");
message("msg", "mode");
message("msg", "mode", 3000);
message("msg", 3000, () => { });

# 联合类型 | 和交叉类型 &

// 联合类型,变量可以声明为多个类型
const fn1 = (type: number | string): string => {
    return type.toString();
}
console.log(fn1('666'));
// 交叉类型,对象作为参数时可以具有多个类的属性,类似于 extends
interface Person {
    name: string,
    age: number
}
interface Man {
    hobby: string
}
const fn2 = (man: Person & Man):void => {
    console.log(man);
}
fn2({
    name:'张三',
    age:18,
    hobby:'唱跳rap'
})

# 断言

const fn = (num: number | string): void => {
    //const length=num.length;// 报错,类型 “string | number” 上不存在属性 “length”。
    console.log((num as string).length);// 告诉编译器传入的 num 一定是 string 类型,编译器不再进行校验
    console.log((<string>num).length);// 第二种方式断言
}
fn('123456')// 输出 6
fn(123456)// 输出 undefined
//

# ts 编写防抖功能

  • 一定时间内连续多次点击只会生效一次
let timer: any;
let clickTest = () => {
clearTimeout(timer);
timer = setTimeout(() => {
    console.log('clicked');
    timer = null;
}, 500)
}
更新于 阅读次数