TypeScript7个实用小技巧

822 阅读3分钟

一.模版字符串类型

可以对模版字符串类型的值进行细化,同时可以识别模版字符串类型的判别式属性

export interface Success {
    type: `${string}Success`;
    body: string;
}

export interface Error {
    type: `${string}Error`;
    message: string;
}

export function handler(r: Success | Error) {
    if (r.type === "HttpSuccess") {
        // 'r' has type 'Success'
        let token = r.body;
    }
}

二.在导入名称前使用 type 修饰符

通过import导入类型变量前通过type声明该引入是一个类型。通过这种方式引入的值会被ts编译器当成类型,而不是某个值。

import type { someType } from './otherfile.ts'

Typescript通常会将无用的import去除掉,但是有时TS无法检测你是否使用了import

// demo1
<!-- A .vue File -->
<script setup>
import { someFunc } from "./some-module.js";
</script>

<button @click="someFunc">Click me!</button>

// demo2
import { Animal } from "./animal.js";
eval("console.log(new Animal().isDangerous())");

在上面的情况你就可以在tsconfig打开preserveValueImports阻止 TypeScript 消除生成的 JavaScript 脚本中的 import 语句。但我们希望TypeScript保留引入的同时 可以去除一些引入的类型,此时我们就可以通过上面使用 type 修饰符的形式引入,这样TypeScript就知道哪些是类型,从而进行安全的去除类型

引用语句支持 type 修饰词(提案PR 4.5)

但是当我们同时开启preserveValueImports 和isolatedModules配置时,isolatedModules会让引入的类型必须是type-only。所以来自同一个文件的数据必须得分两条import引入

import { someFunc, BaseType } from "./some-module.js";
//                 ^^^^^^^^
// Error: 'BaseType' is a type and must be imported using a type-only import

// 除非
import type { BaseType } from "./some-module.js";
import { someFunc } from "./some-module.js"

TypeScript 4.5 允许一个 type 修饰词在 import 语句中

import { someFunc,type BaseType } from "./some-module.js";

三.通过assert断言引入类型(提案PR 4.5)

这个语法可以确保引入的import符合预期

import obj from "./something.json" assert { type: "json" };

// 动态import可以通过第二个参数使用
const obj = await import("./something.json", {
    assert: { type: "json" }
})

四.通过类型守卫进行控制流分析(提案PR 4.4)

利用ts类型检查器理解你的判断,从而推断当前类型

// demo1
function foo(arg: unknown) {
    if (typeof arg === 'string') {
        console.log(arg.toUpperCase());//在TS4.4以下版本会抛出错误'unknown' 类型上不存在 'toUpperCase' 属性
    }
}

// demo2
type Shape =
    | { kind: 'circle'; radius: number }
    | { kind: 'square'; sideLength: number };

function area(shape: Shape): number {
    const isCircle = shape.kind === 'circle';
    if (isCircle) {
        // 知道此处为 circle
        return Math.PI * shape.radius ** 2;
    } else {
        // 知道此处为 square
        return shape.sideLength ** 2;
    }
}

五.as const断言

通过as const断言后将会为表达式推断出它能推断出的最窄或最特定的类型,常用于常量固定

const arr = [1,2,3,4,5] as const
// 等价于
const arr: readonly [1, 2, 3, 4, 5] = [1,2,3,4,5]

六.元组的定义

在 TypeScript 中,元组类型用于表示固定长度和元素类型的数组。

1.基础使用

// 存储了两个数字的元组
let a: [number, number] = [1, 2];

// 包含一个或两个元素的元组。
let c: [string, string?] = ['hello'];
c = ['hello', 'world'];

2....rest

在TS4.2前,TypeScript 只允许 元素位于元组的末尾。

let foo: [number,...string[]];

foo = [123];
foo = [123,'hello'];
foo = [123,'hello!', 'hello!', 'hello!'];

在TS4.2及以后,...rest 可以出现在元组中的任意位置

let foo: [...string[], number];

foo = [123];
foo = ['hello', 123];
foo = ['hello!', 'hello!', 'hello!', 123];

3.元组类型相关数组操作

  • 获取元组类型的长度
const arr = [1,2,3,4,5] as const

type ArrLength = typeof arr['length']; // 5

const arrLength:ArrLength = 4;//不能将类型“4”分配给类型
  • 获取元组所有项组成的联合类型

image.png

七.块级注释

使用块级注释,编辑器在其他地方引入后,可以自动展示注释内容

/** 我是动物信息. */
interface Animal{
    /** 我是狗 */
    dog:Dog,
    /** 我是猫 */
    cat:Cat
}

image.png