TypeScript教程(五)

42 阅读3分钟

上一章我们讲解了Typescript的、type、interface、类型断言、非空断言。接下来我们就来看看字面量类型、类型缩小、函数的类型、函数签名、函数的重载、this类型

字面量类型

字面量类型是 TypeScript 中的一种强类型,用于限定变量只能接受特定的字面值,所以我们的变量的值必须与字面值完全匹配

let color: "red" | "green" | "blue";
color = "red";    // 合法
color = "green";  // 合法
color = "yellow"; // 错误,不匹配任何字面值

类型缩小

类型缩小的英文是 Type Narrowing,是指通过条件语句或其他方法,将一个变量的类型范围缩小到更具体的类型。我们可以通过类似于 typeof padding === "number" 的判断语句,来改变TypeScript的执行路径。在给定的执行路径中,我们可以缩小比声明时更小的类型,这个过程称之为 缩小( Narrowing )。而我们编写的 typeof padding === "number 可以称之为 类型保护(type guards);

常见的类型保护有如下几种:

typeof

在TypeScript 中,typeof 运算符有两种主要用途:

  • 类型查询(Type Query): typeof 可以用于获取变量或表达式的类型。
let x = 10;
let y = "hello";

console.log(typeof x); // 输出: "number"
console.log(typeof y); // 输出: "string"

  • 类型缩小(Type Narrowing): typeof 可以用于在条件语句中缩小变量的类型范围。
function printLength(value: string | number) {
  if (typeof value === "string") {
    // 在这里,typeof value 的结果为 "string"
    console.log(value.length);
  } else {
    // 在这里,typeof value 的结果为 "number"
    console.log(value.toFixed(2));
  }
}

printLength("hello"); // 输出字符串长度
printLength(42);      // 输出数字的小数表示


平等缩小(比如===、!==)

我们可以使用Switch或者相等的一些运算符来表达相等性(比如===, !==, ==, and !=

type Direction = 'left'|'right'|'center'
function turnDirection(direction: Direction){
    switch (direction){
        case 'left' :
            console.log("调用left方法")
            break
    case 'right' :
            console.log("调用right方法")
            break
    case 'center' :
            console.log("调用center方法")
            break
    default:
            console.log("调用默认方法")
  }
}

instanceof

我们可以使用instanceof 运算符帮助我们检查对象缩小范围,

  bark() {
    console.log("Woof!");
  }
}

class Cat {
  meow() {
    console.log("Meow!");
  }
}

function makeSound(animal: Dog | Cat) {
  if (animal instanceof Dog) {
    // 在这里,animal 的类型被缩小为 Dog
    animal.bark();
  } else {
    // 在这里,animal 的类型被缩小为 Cat
    animal.meow();
  }
}

in

in通常用于检查对象是否具有某个属性或者数组是否包含某个元素,我们也可以使用in来帮我们缩小范围

interface Circle {
  radius: number;
}

interface Square {
  sideLength: number;
}

function getArea(shape: Circle | Square): number {
  if ("radius" in shape) {
    // 在这里,shape 的类型被缩小为 Circle
    return Math.PI * shape.radius ** 2;
  } else {
    // 在这里,shape 的类型被缩小为 Square
    return shape.sideLength ** 2;
  }
}

函数的类型

在JavaScript开发中,函数是重要的组成部分,并且函数可以作为一等公民(可以作为参数,也可以作为返回值进行传递)。

那么在使用函数的过程中,函数是否也可以有自己的类型呢?

我们可以用 (num1: number, num2: number) => void的格式去代表一个函数的类型。

  • 接收两个参数的函数:num1和num2,并且都是number类型;
  • 并且这个函数是没有返回值的,所以是void;
//定义函数类型
type AddFunction = (a: number, b: number) => number;

// 使用定义好的函数类型声明变量时,需要遵循相同的参数和返回值规则
const add: AddFunction = (a, b) => {
    return a + b;
};

console.log(add(2, 3));   // 输出 5

可选参数和默认参数

type GreetingFunction = (name?: string, age?: number) => void;

const greet: GreetingFunction = (name = "Anonymous", age = 0) => {
    console.log(`Hello ${name}! You are ${age} years old.`);
};

greet();                       // 输出 "Hello Anonymous! You are 0 years old."
greet("Alice");                // 输出 "Hello Alice! You are 0 years old."
greet("Bob", 25);              // 输出 "Hello Bob! You are 25 years old."

函数的重载

function processInput(input: string): void;
function processInput(input: number): void;

// 实现不同输入对应不同逻辑处理方式 
function processInput(input: any): void {
    if (typeof input === 'string') {
        console.log(`Received a string input: ${input}`);
    } else if (typeof input === 'number') {
        console.log(`Received a number input: ${input}`);
    }
}

processInput("Hello");   // 输出 "Received a string input: Hello"
processInput(10);        // 输出 "Received a number input: 10"

参数的可选类型

我们的函数的参数也是可以设置参数类型的。

function greet(name?: string) {
    if (name) {
        console.log(`Hello ${name}!`);
    } else {
        console.log("Hello!");
    }
}

greet();             // 输出 "Hello!"
greet("Alice");      // 输出 "Hello Alice!"

但是注意:我们的可选类型一定要在必传参数的后面

默认参数

从ES6开始,JavaScript是支持默认参数的,TypeScript也是支持默认参数的

function greet(name: string = "Anonymous") {
    console.log(`Hello ${name}!`);
}

greet();             // 输出 "Hello Anonymous!"
greet("Alice");      // 输出 "Hello Alice!"