初识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 的基础知识,它还有更多高级特性和功能,可以根据项目需求深入学习。

相关推荐
y先森1 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy1 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189112 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿3 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡4 小时前
commitlint校验git提交信息
前端
虾球xz4 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇4 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒4 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员4 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐5 小时前
前端图像处理(一)
前端