初识TS

TypeScript 基础知识

什么是 TypeScript

TypeScript 是 JavaScript 的超集,它为 JavaScript 提供了静态类型检查和其他一些特性,以帮助开发者编写更可维护、可读性更强的代码。TypeScript 最终会被编译为标准的 JavaScript 代码,因此可以运行在任何支持 JavaScript 的环境中。

安装 TypeScript

1.可以使用 npm 安装 TypeScript

js 复制代码
npm install -g typescript

2.编译: tsc 文件名

  • 编辑完成后会在当前文件所在目录的同级, 创建一个名字一样的 JS 文件,内部的 ts 代码会被编译成 js 代码, 原本的 js 代码 原封不动
  • 如果当前文件内, 没有 ts 代码, 全都是 js 代码, 我们可以直接使用 node 运行当前文件;否则会报错, 需要使用 tsc 编译成 js 文件后, 在使用。
  • 安装ts-node:
js 复制代码
   npm i ts-node -g
  • 当前的这个第三方包会给我们提供一个 node 环境, 然后去运行我们的 ts 代码;当前的第三方包在运行的时候, 会自动帮我们把 ts 代码做一个编译处理, 然后将编译完成的代码运行到 node 环境中.
  • 注意: 当前第三方包只会帮我们解析运行 ts 代码, 并不会帮我们创建对应的 js 文件

基本类型

TypeScript 支持多种基本数据类型:

  • number:数字类型
  • string:字符串类型
  • boolean:布尔类型
  • nullundefined:空类型
  • object:对象类型
  • array:数组类型
  • tuple:元组类型
  • enum:枚举类型
  • any:任意类型(any 表示不确定当前变量具体的值是什么, 或者这个变量的值类型有可能会出现多个)
  • void:表示没有任何返回值的函数
ini 复制代码
let num: number = 5;
let str: string = "Hello";
let bool: boolean = true;
let nul: null = null;
let und: undefined = undefined;
let obj: object = { key: "value" };
let arr: number[] = [1, 2, 3];
let tpl: [string, number] = ["tuple", 10];
enum Color { Red, Green, Blue };
let color: Color = Color.Red;
let anyType: any = "anything";
let voidFunc: void = () => { console.log("This function returns nothing."); };

函数

定义函数时可以指定参数类型和返回值类型:

typescript 复制代码
function add(x: number, y: number): number {
  return x + y;
}
​
let result: number = add(3, 5);

数组

在 TypeScript 中,数组可以使用以下方式定义:

js 复制代码
let numbers: number[] = [1, 2, 3, 4, 5];
let strings: string[] = ["apple", "banana", "orange"];

// arr3 是一个数组, 数组内数据的类型, 不做校验
const arr3: any[] = [100, "qf001", true, undefined, null];

// arr4 是一个数组, 数组内的数据是 字符串或者数字
// const arr4: number[] = [100, 'QF001', 200]
// const arr4: string[] = [100, 'QF001', 200]
const arr4: (number | string)[] = [100, "QF001", 200];

// 数组内部是由多个对象组成的
const arr5: { id: number; text: string }[] = [
    { id: 1, text: "qf001" },
    { id: 2, text: "qf002" },
    { id: 3, text: "qf003" },
    { id: 4, text: "qf004" },
];

// 利用接口改造上述代码
interface IArr6 {
    id: number;
    text: string;
}
const arr6: IArr6[] = [
    { id: 1, text: "qf001" },
    { id: 2, text: "qf002" },
    { id: 3, text: "qf003" },
    { id: 4, text: "qf004" },
];

也可以使用数组泛型:

js 复制代码
// 利用 泛型 添加数组类型
interface IArr7 {
    id: number;
    text: string;
}

const arr7: Array<IArr7> = [
    { id: 1, text: "qf001" },
    { id: 2, text: "qf002" },
    { id: 3, text: "qf003" },
    { id: 4, text: "qf004" },
];

const arr8: Array<number> = [1, 2, 3];
const arr9: Array<string> = ["1", "2", "3"];

数组元素的访问和操作:

ini 复制代码
let numbers: number[] = [1, 2, 3, 4, 5];
let firstNumber: number = numbers[0]; // 访问第一个元素
numbers.push(6); // 添加元素
numbers.pop(); // 移除最后一个元素

对象

在 TypeScript 中,对象是一种复合值,它可以包含多个属性,每个属性都有自己的名称和值。以下是一些关于对象的基础知识:

1. 对象的定义

对象可以通过直接赋值或使用接口来定义:

  • interface 接口名 (一般: I + 变量的名字) {}
typescript 复制代码
// 直接赋值
let person: { name: string; age: number } = {
  name: "John",
  age: 30,
};

// 使用接口
interface Person {
  name: string;
  age: number;
}

let anotherPerson: Person = {
  name: "Jane",
  age: 25,
};

//接口的嵌套
interface IObj {
    name: string,
    id: number,
    info: {
        width: number,
        height: number,
        bo: boolean
    }
}

// 如果 接口IInfo 使用次数比较多, 可以抽离出来, 否则不建议
interface IInfo {
    width: number;
    height: number;
    bo: boolean;
}

interface IObj {
    name: string;
    id: number;
    info: IInfo
}

const obj: IObj = {
    name: "qf001",
    id: 10086,
    info: {
        width: 100,
        height: 200,
        bo: true,
    },
};

// obj.info.bo = '10086'   // 不能将类型 "string" 分配给类型 "boolean"

console.log(obj.info.bo);

2. 可选属性

在接口中,你可以使用问号 ? 表示属性是可选的:

typescript 复制代码
interface Car {
  brand: string;
  model?: string; // 可选属性
  year: number;
}

let myCar: Car = {
  brand: "Toyota",
  year: 2020,
};

3. 只读属性

你可以使用 readonly 关键字使属性成为只读的:

typescript 复制代码
interface Point {
  readonly x: number;
  readonly y: number;
}

let point: Point = { x: 10, y: 20 };
// point.x = 30; // 编译错误,无法修改只读属性

4. 函数作为属性

对象的属性可以是函数,被称为方法:

typescript 复制代码
interface Greeter {
  greet(): string;
}

let myGreeter: Greeter = {
  greet() {
    return "Hello, TypeScript!";
  },
};

5. 类型断言和对象

使用类型断言可以告诉编译器对象的实际类型:

typescript 复制代码
let value: any = "Hello, TypeScript!";
let strLength: number = (value as string).length;

6. 展开运算符

使用展开运算符 ... 可以合并对象的属性:

typescript 复制代码
let defaults: { food: string; price: number } = { food: "Pizza", price: 10 };
let order: { toppings: string[]; } = { toppings: ["Cheese", "Pepperoni"], ...defaults };

这是一些关于对象的基础知识。对象是 TypeScript 中非常重要的数据结构,对于表示数据和组织代码结构都起着关键作用。

函数

基本函数

typescript 复制代码
function add(x: number, y: number): number {
  return x + y;
}
​
let result: number = add(3, 5);

1. 无参无返函数

javascript 复制代码
function greet(): void {
  console.log("Hello!");
}
​
greet();

解释: 无参无返函数表示该函数不接受任何参数,也不返回任何值。在上面的例子中,greet 函数用于打印简单的问候语,没有输入参数,也没有返回值。

2. 无参有返函数

typescript 复制代码
function getRandomNumber(): number {
  return Math.random();
}
​
let randomNum: number = getRandomNumber();

// 无参有返
function fn2(): void {
    return undefined;
}
function fn3(): undefined {
    return undefined;
}
function fn4(): number {
    return 100;
}
function fn5(): string {
    return "qf_001";
}
function fn6(): { id: number; name: string } {
    return { id: 1, name: "张三" };
}
interface IFn7 {
    id: number;
    name: string;
}
function fn7(): IFn7 {
    return { id: 1, name: "张三" };
}
function fn8(): number[] {
    return [1, 2, 3];
}
function fn9(): Array<string> {
    return ["1", "2", "3"];
}

解释: 无参有返函数表示该函数不接受任何参数,但会返回一个值。在这个例子中,getRandomNumber 函数返回一个随机数,因此它的类型为 number。通过调用该函数,可以获得一个随机数并存储在变量 randomNum 中。

3. 有参无返函数

js 复制代码
function greetPerson(name: string): void {
  console.log(`Hello, ${name}!`);
}
​
greetPerson("John");

// 有参无返
function fn10(a: number, b: string): void {}

解释: 有参无返函数表示该函数接受一个或多个参数,但不返回任何值。在上面的例子中,greetPerson 函数接受一个 name 参数,用于向控制台输出对特定人的问候语。

4. 有参有返函数

js 复制代码
// 有参有返
function fn11(a: number, b: number): number {
    return a + b;
}

// const fn12: number = 100
// const fn12: string = "qf001";

const fn12: (a: number, b: number) => number = function (
    a: number,
    b: number
): number {
    return a + b;
};
const fn13: (a: number, b: number) => void = function (
    a: number,
    b: number
): void {};
const fn14: () => void = function (): void {};

// 1. 赋值式创建的一个普通函数
// const fn15 = function (a, b) { return a + b }

// 2. 将普通函数改造成 箭头函数
// const fn15 = (a, b) => { return a + b }

// 3. 利用箭头函数的语法, 简化我们的代码
// const fn15 = (a, b) => a + b;

// 4. 给函数的形参添加类型校验
// const fn15 = (a: number, b: number) => a + b;

// 5. 给函数的返回值添加类型校验
// const fn15 = (a: number, b: number): number => a + b;

// 6. 给变量添加一个类型校验
const fn15: (a: number, b: number) => number = (a: number, b: number): number => a + b;

解释: 有参有返函数表示该函数接受一个或多个参数,并返回一个值。在这个例子中,add 函数接受两个参数 xy,并返回它们的和。通过调用该函数,可以得到两个数字的和,并将结果存储在变量 sum 中。

这四种基本的函数类型展示了函数在 TypeScript 中的常见用法,从简单的问候语到执行数学运算,你可以根据需要选择适当的函数类型。

可选参数和默认参数

  • 可选参数:
typescript 复制代码
function greet(name: string, greeting?: string): string {
  if (greeting) {
    return `${greeting}, ${name}!`;
  } else {
    return `Hello, ${name}!`;
  }
}
​
let greeting1: string = greet("John"); // 输出 "Hello, John!"
let greeting2: string = greet("Jane", "Good morning"); // 输出 "Good morning, Jane!"
  • 默认参数:
typescript 复制代码
function greet(name: string, greeting: string = "Hello"): string {
  return `${greeting}, ${name}!`;
}
​
let result: string = greet("John"); // 输出 "Hello, John!"

接口

接口用于定义对象的结构,提高代码的可读性和可维护性:

ini 复制代码
interface Person {
  name: string;
  age: number;
}
​
let person: Person = { name: "John", age: 30 };

接口合并

  • TS 中 允许我们的接口名重复, TS 会将我们两个接口 做一个合并
  • 后续属性声明必须属于同一类型
  • 所有接口中都可以按照下列的方式添加一个可选的属性, 也就是对象中这个属性可有可无, 但是如果有必须按照接口中指定的数据类型
js 复制代码
  text?: string   // 对象中可以没有 text 属性, 但是如果有这个属性, 那么属性值必须是 字符串类型
js 复制代码
   interface IObj {
    id: number;
    name: string;
}

interface IObj {
    // 属性名相同
    // id: string  // 后续属性声明必须属于同一类型 (此时 id 的属性值, 必须是 number)
    id: number

    // 属性名不相同
    age: number

    text?: string   // 对象中可以没有 text 属性, 但是如果有这个属性, 那么属性值必须是 字符串类型
}

const obj: IObj = {
    id: 1,
    name: "张三",
    age: 18
};
const obj1: IObj = {
    id: 2,
    name: '李四',
    age: 28,
    // text: 'qf001'
    // text: 100
    // text: true
} 

泛型

泛型允许你编写能够适用于不同类型的代码,提高代码的复用性:

js 复制代码
function identity<T>(arg: T): T {
  return arg;
}
​
let result: string = identity("Hello");
let anotherResult: number = identity(42);
  • 需求: 封装一个函数, 接受两个参数, 一个是数组的长度, 一个是数组内填充的内容, 这个函数根据两个形参创建出来一个数组, 然后返回出来
js 复制代码
    // 2. 添加 ts 类型校验
function createArr(length: number, value: any): any[] {
    // 根据 形参创建出来一个数组
    const arr: any[] = [];
    for (let i = 0; i < length; i++) {
        arr.push(value);
    }
    return arr;
}

const arr1 = createArr(3, "数组填充");
console.log(arr1); // ['数组填充', '数组填充', '数组填充']

const arr2 = createArr(5, true);
console.log(arr2); // [true, true, true, true, true]

const arr3 = createArr(2, 10086);
console.log(arr3); // [10086, 10086]

const arr4 = createArr(3, { text: "对象用于填充数组" });
console.log(arr4)

// 3. 利用泛型优化上述代码
function createArr<T>(length: number, value: T): T[] {
    // 根据 形参创建出来一个数组
    const arr: T[] = [];
    for (let i = 0; i < length; i++) {
        arr.push(value);
    }
    return arr;
}

const arr1: string[] = createArr<string>(3, "数组填充");
console.log(arr1); // ['数组填充', '数组填充', '数组填充']

const arr2: boolean[] = createArr<boolean>(5, true);
console.log(arr2); // [true, true, true, true, true]

const arr3: number[] = createArr<number>(2, 10086);
console.log(arr3); // [10086, 10086]

interface IObj {
    text: string;
}
const arr4: IObj[] = createArr<IObj>(3, { text: "对象用于填充数组" });
// const arr4: { text: string }[] = createArr<{ text: string }>(3, { text: "对象用于填充数组" });
console.log(arr4);

类型别名(Type)

在 TypeScript 中,类型别名(Type Alias)是一种给一个类型起别名的方式,可以提高代码的可读性和复用性。以下是有关类型别名的基础知识:

1. 基本类型别名

可以使用 type 关键字为基本类型创建别名:

typescript 复制代码
type ID = number;
type Username = string;

let userId: ID = 1;
let username: Username = "john_doe";

2. 对象类型别名

可以使用类型别名为对象类型创建别名:

typescript 复制代码
type Point = {
  x: number;
  y: number;
};

let point: Point = { x: 10, y: 20 };

3. 函数类型别名

可以使用类型别名为函数类型创建别名:

typescript 复制代码
type AddFunction = (x: number, y: number) => number;

let add: AddFunction = (a, b) => a + b;

4. 泛型类型别名

类型别名也可以使用泛型:

typescript 复制代码
type Pair<T, U> = {
  first: T;
  second: U;
};

let pair: Pair<number, string> = { first: 1, second: "two" };

5. 字符串字面量类型别名

使用类型别名可以创建字符串字面量类型:

typescript 复制代码
type Direction = "left" | "right" | "up" | "down";
let direction: Direction = "left";

6. 类型别名 vs. 接口

类型别名和接口在很多情况下是可以互换使用的,但也有一些区别。通常,当你需要扩展或实现时,使用接口更为合适;而在其他情况下,使用类型别名可能更简洁。

  • type 也可以完成 interface 的功能, 两者最大的区别就是 type 需要=
    • 一般在开发的时候, 我们如果是给对象添加类型校验我们会选择 interface
    • type 一般更多的是给 字符串使用
    • type 内部的属性可以用 换行/逗号/分号
typescript 复制代码
// 使用接口
interface Person {
  name: string;
  age: number;
}

// 使用类型别名
type Point = {
  x: number;
  y: number;
};

类型别名是 TypeScript 中强大而灵活的一部分,它使得我们能够更清晰地定义和组织各种类型。

枚举(Enum)

在 TypeScript 中,枚举(Enum)是一种用于命名一组命名常量的数据类型,使代码更具可读性。以下是有关枚举的基础知识:

1. 枚举基础

使用 enum 关键字定义枚举:

typescript 复制代码
enum Direction {
  Up,
  Down,
  Left,
  Right,
}

默认情况下,枚举的值从 0 开始,依次递增。在上面的例子中,Direction.Up 的值为 0,Direction.Down 的值为 1,以此类推。

2. 指定枚举值

可以为枚举的成员指定具体的值:

typescript 复制代码
enum Direction {
  Up = 1,
  Down,
  Left = 3,
  Right,
}

在这个例子中,Direction.Up 的值为 1,Direction.Down 的值为 2,Direction.Left 的值为 3,Direction.Right 的值为 4。

3. 字符串枚举

枚举的成员可以是字符串:

typescript 复制代码
enum Day {
  Monday = "Monday",
  Tuesday = "Tuesday",
  Wednesday = "Wednesday",
  Thursday = "Thursday",
  Friday = "Friday",
  Saturday = "Saturday",
  Sunday = "Sunday",
}

4. 计算和常量成员

枚举成员可以是计算出来的值或常量值:

typescript 复制代码
enum FileAccess {
  // 常量成员
  None,
  Read = 1 << 1,
  Write = 1 << 2,
  ReadWrite = Read | Write, // 计算成员
}

5. 反向映射

枚举可以通过值反向映射到相应的名称:

typescript 复制代码
enum Direction {
  Up,
  Down,
  Left,
  Right,
}

let directionName: string = Direction[1]; // 得到 "Down"

6. 枚举用法

枚举在代码中的应用场景包括状态表示、选项集合等。例如:

typescript 复制代码
enum TrafficLight {
  Red,
  Yellow,
  Green,
}

function getTrafficLightMessage(light: TrafficLight): string {
  switch (light) {
    case TrafficLight.Red:
      return "Stop";
    case TrafficLight.Yellow:
      return "Slow down";
    case TrafficLight.Green:
      return "Go";
    default:
      return "Unknown light";
  }
}

let message: string = getTrafficLightMessage(TrafficLight.Yellow);
console.log(message); // 输出 "Slow down"

枚举提供了一种更具可读性的方式来表示一组常量,并且在一些场景中能够更好地反映代码的意图。

类是面向对象编程的基础,TypeScript 支持类和继承:

scala 复制代码
class Animal {
  name: string;
​
  constructor(name: string) {
    this.name = name;
  }
​
  makeSound(): void {
    console.log("Some generic sound");
  }
}
​
class Dog extends Animal {
  makeSound(): void {
    console.log("Bark");
  }
}
​
let myDog: Dog = new Dog("Buddy");
myDog.makeSound(); // 输出 "Bark"

模块

TypeScript 支持模块化开发,可以使用 importexport 关键字:

typescript 复制代码
// math.ts
export function add(x: number, y: number): number {
  return x + y;
}
​
// app.ts
import { add } from "./math";
​
let result: number = add(3, 5);

类型断言

类型断言用于告诉编译器变量的实际类型,类似于类型转换:

ini 复制代码
let value: any = "Hello, TypeScript!";
let strLength: number = (value as string).length;

这只是 TypeScript 的基础知识,它还有更多高级特性和功能,可以根据项目需求深入学习。

相关推荐
dream_ready1 小时前
linux安装nginx+前端部署vue项目(实际测试react项目也可以)
前端·javascript·vue.js·nginx·react·html5
编写美好前程1 小时前
ruoyi-vue若依前端是如何防止接口重复请求
前端·javascript·vue.js
flytam1 小时前
ES5 在 Web 上的现状
前端·javascript
喵喵酱仔__1 小时前
阻止冒泡事件
前端·javascript·vue.js
GISer_Jing1 小时前
前端面试CSS常见题目
前端·css·面试
八了个戒1 小时前
【TypeScript入坑】什么是TypeScript?
开发语言·前端·javascript·面试·typescript
不悔哥1 小时前
vue 案例使用
前端·javascript·vue.js
anyup_前端梦工厂2 小时前
Vuex 入门与实战
前端·javascript·vue.js
你挚爱的强哥3 小时前
【sgCreateCallAPIFunctionParam】自定义小工具:敏捷开发→调用接口方法参数生成工具
前端·javascript·vue.js
米老鼠的摩托车日记3 小时前
【vue element-ui】关于删除按钮的提示框,可一键复制
前端·javascript·vue.js