2024-08-16
/**
 * 计算两个数的和
 * @param {number} a 第一个加数
 * @param {number} b 第二个加数
 * @returns {number} 两数之和
 */
function add(a, b) {
  return a + b;
}

// 使用
console.log(add(1, 2)); // 输出: 3
JavaScript

这段代码展示了如何在JavaScript或TypeScript中使用JSDoc注释来描述一个函数的用途和参数,从而使得代码更具可读性和自文档性。注释以/**开始,并在需要文档化的函数、方法或变量上方添加。@param描述参数,@returns描述返回值。这样的注释可以被工具如TypeScript或编辑器如Visual Studio Code解析,以提供自动完成和快速信息。

2024-08-16
// 定义一个接口来描述一个用户的属性
interface User {
  id: number;
  name: string;
  email: string;
  age?: number; // age是可选的
}

// 定义一个函数,接收一个User类型的参数
function greet(user: User) {
  return `Hello, ${user.name}!`;
}

// 使用可选属性创建一个用户对象
const user1: User = { id: 1, name: 'Alice', email: 'alice@example.com' };

// 使用完整属性创建另一个用户对象
const user2: User = { id: 2, name: 'Bob', email: 'bob@example.com', age: 30 };

// 调用函数并打印结果
console.log(greet(user1)); // 输出: Hello, Alice!
console.log(greet(user2)); // 输出: Hello, Bob!
TypeScript

这个代码示例定义了一个User接口,该接口描述了用户对象应有的属性和类型。然后定义了一个greet函数,该函数接受一个User类型的参数,并返回一个问候字符串。最后,我们创建了两个用户对象并调用了greet函数。这个示例展示了如何在TypeScript中使用接口来规定对象的结构,并且如何处理可选属性。

2024-08-16
import { Injectable, Scope } from '@nestjs/common';
import * as winston from 'winston';

@Injectable({ scope: Scope.TRANSIENT })
export class LoggingService {
  private logger: winston.Logger;

  constructor() {
    this.logger = winston.createLogger({
      level: 'info',
      format: winston.format.json(),
      transports: [
        new winston.transports.File({ filename: 'combined.log' }),
      ],
    });
  }

  logInfo(message: string) {
    this.logger.info(message);
  }

  logError(message: string) {
    this.logger.error(message);
  }
}
TypeScript

这段代码定义了一个服务类LoggingService,它使用Winston库来创建日志记录器。服务实例的范围设置为Scope.TRANSIENT,意味着每次注入时都会创建一个新的服务实例。logInfologError方法用于记录信息和错误日志。这个例子展示了如何在NestJS应用中使用Winston进行日志管理。

2024-08-16

在TypeScript中,组件和DOM事件的参数类型可以有很多种,但最常见的几种包括:

  1. MouseEvent<T>:用于鼠标事件,其中T通常是HTMLButtonElementHTMLDivElement等DOM元素类型。
  2. KeyboardEvent<T>:用于键盘事件,其中T通常是HTMLInputElementHTMLTextAreaElement等表单元素类型。
  3. FocusEvent<T>:用于焦点事件,其中T通常是HTMLInputElementHTMLTextAreaElement等表单元素类型。
  4. FormEvent<T>:用于表单事件,其中T通常是HTMLFormElement等表单元素类型。

以下是一些示例代码:

import { MouseEventHandler, KeyboardEventHandler, FocusEventHandler, FormEventHandler } from 'react';

// 示例1: 鼠标点击事件
const handleClick: MouseEventHandler<HTMLButtonElement> = (event) => {
  console.log(event.clientX, event.clientY);
};

// 示例2: 键盘按键事件
const handleKeyPress: KeyboardEventHandler<HTMLInputElement> = (event) => {
  console.log(event.key);
};

// 示例3: 输入框获得焦点事件
const handleFocus: FocusEventHandler<HTMLInputElement> = (event) => {
  console.log(event.target.value);
};

// 示例4: 表单提交事件
const handleSubmit: FormEventHandler<HTMLFormElement> = (event) => {
  event.preventDefault(); // 阻止表单默认提交行为
  console.log('Form submitted');
};
TypeScript

这些是React中的例子,但是在其他框架或纯TypeScript项目中,你可能会看到类似的类型定义。

2024-08-16
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';

@ApiTags('用户管理')
@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }

  @Get()
  findAll() {
    return this.usersService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(+id);
  }

  @Patch(':id')
  update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
    return this.usersService.update(+id, updateUserDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.usersService.remove(+id);
  }
}
TypeScript

这段代码展示了如何在NestJS框架中创建一个RESTful API控制器,它包含了基本的CRUD操作。使用了@Controller装饰器来定义一个控制器,并且通过@Get@Post@Patch@Delete装饰器来处理对应的HTTP请求。同时,使用了DTO(数据传输对象)来定义请求体的结构,并且通过Body装饰器来绑定请求体到DTO。这个例子简洁明了,并且清晰地展示了如何在实际应用中使用NestJS框架。

2024-08-16
// 定义装饰器工厂
function logClassMetadata(target: any) {
  console.log(`类名: ${target.name}`);
}

// 使用装饰器
@logClassMetadata
class MyClass {
  // 类的成员
}

// 执行上述装饰器后,会在控制台输出 MyClass 这个类名
TypeScript

这个例子展示了如何定义一个简单的装饰器工厂,并且如何在TypeScript中使用它来装饰一个类。当装饰器被应用到MyClass上时,它会触发装饰器工厂函数,并将被装饰的类作为参数传入,然后输出这个类的名字。这是学习TypeScript装饰器的一个基本例子。

2024-08-16
module.exports = {
  root: true,
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
    sourceType: 'module'
  },
  extends: [
    'plugin:vue/vue3-recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier/@typescript-eslint',
    'plugin:prettier/recommended'
  ],
  rules: {
    // 在这里添加或覆盖 ESLint 规则
  }
};
JavaScript

这个配置文件为 TypeScript 和 Vue 项目设置了 ESLint,并且整合了 Prettier 来统一代码风格。它首先指定了项目根目录,然后指定了解析器为 vue-eslint-parser@typescript-eslint/parser,以正确解析 .vue 文件和 TypeScript 代码。接着,它扩展了几个推荐的 ESLint 插件规则列表,分别对应 Vue 3、TypeScript 和 Prettier 整合。最后,可以在 rules 对象中自定义或覆盖规则。

2024-08-16

在TypeScript中,断言函数是一种告诉编译器你确信代码的方式。这样可以在不改变运行时行为的情况下,去除类型检查的一些不必要的限制。

TypeScript中的断言有两种形式:

  1. 类型断言:

类型断言指的是在运行时不会进行任何检查的方式来告诉TypeScript编译器变量的类型。

例如,假设我们有一个变量 value,它的类型被定义为 unknown

let value: unknown = 'Hello, World!';
TypeScript

如果我们想要断言 value 的类型为 string,我们可以使用如下的语法:

let strLength = (value as string).length;
TypeScript
  1. 自定义类型保护:

自定义类型保护是一种特殊的断言,它允许你在代码中添加运行时检查。

例如,我们可以创建一个函数,该函数接收一个 unknown 类型的参数,并断言它是一个 string 类型:

function isString(value: unknown): value is string {
  return typeof value === 'string';
}

let value: unknown = 'Hello, World!';

if (isString(value)) {
  console.log(value.toUpperCase());  // 在这里,TypeScript 知道 `value` 是一个字符串
}
TypeScript

在这个例子中,value is string 就是一个自定义的类型保护。它告诉TypeScript,valueisString 函数内部的代码块中是一个 string 类型。

2024-08-16
<template>
  <el-menu
    :default-active="defaultActive"
    class="el-menu-vertical-demo"
    @open="handleOpen"
    @close="handleClose"
  >
    <template v-for="item in menuItems" :key="item.index">
      <el-sub-menu v-if="item.children && item.children.length" :index="item.index">
        <template #title>
          <i :class="item.icon"></i>
          <span>{{ item.title }}</span>
        </template>
        <side-menu-item
          v-for="subItem in item.children"
          :key="subItem.index"
          :item="subItem"
        />
      </el-sub-menu>
      <el-menu-item v-else :index="item.index">
        <i :class="item.icon"></i>
        <template #title>{{ item.title }}</template>
      </el-menu-item>
    </template>
  </el-menu>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue';
import type { MenuItem } from './types';

export default defineComponent({
  name: 'SideMenu',
  props: {
    menuItems: {
      type: Array as PropType<MenuItem[]>,
      default: () => [],
    },
    defaultActive: {
      type: String,
      default: '',
    },
  },
  setup(props, { emit }) {
    const handleOpen = (index: string, indexPath: string) => {
      emit('open', index, indexPath);
    };

    const handleClose = (index: string, indexPath: string) => {
      emit('close', index, indexPath);
    };

    return {
      handleOpen,
      handleClose,
    };
  },
});
</script>
Vue

这个代码实例展示了如何在Vue 3和TypeScript中创建一个可以接收menuItems属性的侧边栏菜单组件。它使用了el-menuel-sub-menu组件来构建多级菜单,并通过props传递菜单数据。setup函数中定义了处理菜单打开和关闭事件的方法,并通过emit将这些事件向上传递给父组件。

2024-08-16
# 安装 Vite 工具
npm init vite@latest

# 运行上述命令后,按照提示进行操作
# 选择模板:vanilla
# 输入项目名称:my-vue-ts-project
# 选择框架:Vue
# 选择JavaScript框架:TypeScript
# 确认项目目录:确保目录正确

# 进入项目目录
cd my-vue-ts-project

# 安装依赖
npm install

# 启动开发服务器
npm run dev
Bash

以上命令将会创建一个名为 my-vue-ts-project 的新 Vue 项目,并使用 TypeScript 作为编程语言。安装完成后,你可以通过运行 npm run dev 来启动开发服务器,并在浏览器中预览你的新项目。