Skip to content

ts基础

基本数据类型

ts
// 字符串类型
const name: string = 'zhangsan'
// 数值类型
const age: number = 15
const hex: number = 0xff

// 布尔类型
const adult: boolean = false
const graduated: boolean = 0

any类型

any,可以是如何类型,不推荐使用

ts
let anyData: any = 123
anyData = 'zhangsan'
anyData = true

unknown类型

unkonwn,表示未知类型,会自动推导第一次赋值的类型

ts
let unkonwnData: unkonwn
unkonwnData = 123
unkonwnData = 'zhangsan' // 报错: 类型“string”的参数不能赋给类型“number”的参数

void类型

void,表示空类型,表示没有返回值

ts
function print(): void {
    console.log('hello world')
}

never类型

never,表示永远不会有返回的类型

  • 如抛出异常
  • 死循环
ts
function error(message: string): never {
    throw new Error(message)
}

function infiniteLoop(): never {
    while (true) {
    }
}

使用场景

它是所有类型的子类型,但没有任何类型是它的子类型(除了自身),主要用于:

  • 永远不结束的函数:如抛错函数、无限循环函数;
  • 类型收窄到不存在:结合条件判断,标记「不可能触发的分支」;
  • 排除联合类型的所有可能:实现严格的类型穷尽检查。
vue

<script setup lang="ts">
  import {ref} from 'vue';

  const number = ref(0);
  // 字面类型
  type Fruit = "apple" | "banana" | "orange";

  function getFruitPrice(fruit: Fruit): number {
    switch (fruit) {
      case "apple":
        return number.value = 5;
      case "banana":
        return number.value = 3;
      case "orange":
        return number.value = 4;
      default:
        const _exhaustiveCheck: never = fruit;
        throw new Error(`未知水果:${_exhaustiveCheck}`);
    }
  }
</script>

<template>
  {{ number }}
  <button @click="getFruitPrice('apple')">苹果</button>
  <button @click="getFruitPrice('banana')">香蕉</button>
  <button @click="getFruitPrice('watermelon')">西瓜</button>
</template>

对于never和void类型

  • 两者都可表示空类型,但never比void更严格,never表示永远不存在的值,而void表示可以返回undefined。
  • never类型不能赋值给任何类型,而void类型可以赋值给any类型。
  • never类型表示一个不存在的值,比如never类型表示一个函数会永远不返回。
  • void类型表示一个函数会返回undefined,或者没有返回值。

null和undefined类型

ts
let name: string | null = null
let age: number | undefined = undefined

javaScript 有两个基础值用于表示值不存在或未初始化的值:null 和 undefined。 TypeScript 有两个对应的同名类型。这些类型的行为取决于你是否启用了 strictNullChecks 选项。

关闭 strictNullChecks,可能是 nullundefined 的值仍然可以正常访问,并且值 nullundefined 可以分配给任何类型的属性。缺乏对这些值的检查往往是错误的主要来源;

启用 strictNullChecks 时,当值为 null 或 undefined 时,你需要在对该值使用方法或属性之前测试这些值。就像在使用可选属性之前检查 undefined 一样,我们可以使用缩小来检查可能是 null 的值:

ts
function doSomething(x: string | null) {
    if (x === null) {
        // do nothing
    } else {
        console.log("Hello, " + x.toUpperCase());
    }
}

联合类型

联合类型,表示多个类型中的一个

ts
let name: string | number = 'zhangsan'
name = 123
name = true // 错误: 类型“boolean”的参数不能赋给类型“string | number”的参数

非空断言

TypeScript 还具有一种特殊的语法,可以在不进行任何显式检查的情况下从类型中删除 null 和 undefined。在任何表达式之后写 ! 实际上是一个类型断言,该值不是 null 或 undefined:

ts
let name: string | null = null
name!.toUpperCase()
name.toUpperCase() // 错误: 类型“null”上不存在属性“toUpperCase”

对象类型

创建对象类型,对象类型可以包含多个属性,属性类型可以任意,属性名可以任意

ts
// 固定类型
type Person = {
    name: string;
    age: number;
    sex?: string; // 可选属性
}

const person1: Person = {
    name: 'zhangsan',
    age: 18
}
const person2: Person = {
    name: 'lisi',
    age: 19,
    sex: 'male'
}

const person3: Person = {
    name: 'wangwu',
    sex: 'female'
} // 错误: 属性“age”缺少,或者属性“age”的类型不匹配

// 泛型映射类型
// T表示键名类型,U表示键值类型
type Animal<T, U> = {
    [key in T]: U;
}

// 比如给猫定义属性
const car: Animal<string, number> = {
    speed: 100,
    weight: 2000
}

// 统计家禽的数量
const fowl: Animal<'chicken' | 'durk', number> = {
    chicken: 18,
    durk: 16
}

数组和元组

数组和元组,数组和元组都是有序的集合,数组和元组可以包含多个元素,元素类型可以任意,元组可以指定元素类型和数量。

特征数组元组
长度约束不限制声明时确定长度
类型约束不限制确定类型和数量
赋值约束不限制赋值时类型和数量必须一致
越界访问undefined报错
使用场景存储同类数据(如列表、数据集)存储结构化数据(如坐标、返回值、键值对)

数组

ts
// 数组类型的声明方式
let numbers: number[] = [1, 2, 3, 4, 5];
let strings: Array<string> = ["hello", "world"];
let numbers2: number[] = Array.from({length: 10}).map((_, index) => index + 1)

// 联合类型数组
let mixed: (number | string)[] = [1, "hello", 2, "world"];

// 只读数组
let readonlyNumbers: readonly number[] = [1, 2, 3];
let readonlyStrings: ReadonlyArray<string> = ["a", "b", "c"];

// 多维数组
let matrix: number[][] = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

元组

ts
// 基本元组
let person: [string, number] = ["张进喜", 25];

// 可选元素
let optional: [string, number?] = ["hello"];

// 剩余元素
let rest: [string, ...number[]] = ["hello", 1, 2, 3];

// 只读元组
type StringNumberBooleans = readonly [string, number, ...boolean[]];
const tuple: StringNumberBooleans = ["world", 3, true, false, true];

// 命名元组
type Range = [start: number, end: number];
let range: Range = [0, 100];

// 元组解构
let [name, age] = person;
console.log(`姓名: ${name}, 年龄: ${age}`);

枚举

枚举,枚举是一种数据结构,用于定义一组常量,枚举成员会自动赋值,从0开始递增。

ts
enum Direction {
    up = 1,
    down,
    left,
    right
}

enum Color {
    Red = "#ff0000",
    Green = "#00ff00",
    Blue = "#0000ff"
}

类型断言

类型断言,用于告诉编译器变量的类型,编译器会忽略类型检查。

ts
const container = document.getElementById("container") as HTMLDivElement;

const name: string | null = 'zhangsan'
name.length // 错误: 类型“string | null”上不存在属性“length”
    (name as string).length // 正确

字面类型

字面类型,用于定义一个值只能是某个具体的值。

ts
let x: "hello" = "hello";
// OK
x = "hello";
// 错误:值“howdy”与类型“"hello"`不匹配
x = "howdy";

显然,这种类型是无意义的对于绝大多数场景来说 但可以结合之前使用过的联合类型

ts
function printText(s: string, alignment: "left" | "right" | "center") {
    // ...
}

printText("Hello, world", "left");
printText("G'day, mate", "centre");// 错误:值“centre”与类型“"left" | "right" | "center"`不匹配

这是我的个人文档