引言
TypeScript作为JavaScript的超集,通过引入静态类型检查和现代化的语法特性,为前端开发带来了前所未有的开发体验。在大型项目中,TypeScript的工程化实践显得尤为重要。本文将深入探讨从项目初始化到团队协作的完整开发流程,帮助开发团队建立高效的TypeScript开发环境和工作流程。
项目初始化配置
1.1 TypeScript基础环境搭建
在开始任何TypeScript项目之前,我们需要搭建基础的开发环境。首先,创建项目目录并初始化npm包:
mkdir my-typescript-project
cd my-typescript-project
npm init -y
接下来安装TypeScript开发依赖:
npm install -D typescript @types/node
1.2 tsconfig.json配置详解
tsconfig.json是TypeScript项目的核心配置文件,合理的配置能够显著提升开发体验和构建效率。以下是一个生产级别的配置示例:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"types": ["node"],
"allowJs": true,
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"removeComments": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"exactOptionalPropertyTypes": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictConstructorChecks": true,
"strictPropertyInitialization": true,
"noImplicitAny": true,
"noImplicitThis": true,
"useUnknownInCatchVariables": true,
"alwaysStrict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"exactOptionalPropertyTypes": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist"
]
}
这个配置文件包含了以下关键特性:
- 严格模式:启用所有严格检查选项,确保代码质量
- 模块解析:使用Node.js模块解析策略
- 目标兼容性:设置为ES2020,支持现代JavaScript特性
- 类型检查:启用全面的类型检查,包括严格模式下的各种检查
1.3 项目目录结构设计
良好的目录结构是工程化实践的基础。以下是一个推荐的项目结构:
my-typescript-project/
├── src/
│ ├── components/
│ ├── services/
│ ├── utils/
│ ├── types/
│ └── index.ts
├── tests/
├── dist/
├── config/
├── .vscode/
├── .gitignore
├── package.json
└── tsconfig.json
类型系统设计
2.1 类型定义最佳实践
在大型项目中,合理的类型设计能够显著提升代码的可维护性和可读性。以下是一些关键的类型设计原则:
// 定义基础类型
export type UserId = string;
export type UserName = string;
export type UserStatus = 'active' | 'inactive' | 'pending';
// 使用接口定义对象结构
export interface User {
id: UserId;
name: UserName;
email: string;
status: UserStatus;
createdAt: Date;
updatedAt: Date;
}
// 使用泛型创建可复用的类型
export interface ApiResponse<T> {
success: boolean;
data: T;
message?: string;
error?: string;
}
// 使用联合类型处理多种可能的值
export type Result<T, E = Error> = { success: true; data: T } | { success: false; error: E };
// 使用条件类型创建更复杂的类型
export type NonNullable<T> = T extends null | undefined ? never : T;
export type PickByType<T, U> = {
[K in keyof T]: T[K] extends U ? K : never;
}[keyof T];
2.2 类型工具函数
为了提高类型系统的灵活性,我们可以创建一些实用的类型工具函数:
// 从对象中排除某些属性
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
// 从对象中选择某些属性
export type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
// 使对象属性变为可选
export type Partial<T> = {
[P in keyof T]?: T[P];
};
// 使对象属性变为只读
export type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
// 从数组类型中提取元素类型
export type ElementOf<T> = T extends (infer U)[] ? U : never;
// 创建可选属性的类型
export type Optional<T> = {
[P in keyof T]?: T[P];
};
2.3 高级类型模式
在复杂项目中,我们需要使用更高级的类型模式来处理复杂的业务逻辑:
// 使用映射类型创建属性转换
export type CamelToKebab<T> = T extends `${infer First}${infer Rest}`
? `${First}${Rest extends Capitalize<Rest> ? '-' : ''}${CamelToKebab<Rest>}`
: T;
// 使用类型守卫进行运行时类型检查
export function isUser(obj: any): obj is User {
return (
typeof obj === 'object' &&
obj !== null &&
typeof obj.id === 'string' &&
typeof obj.name === 'string' &&
typeof obj.email === 'string'
);
}
// 使用类型别名创建复杂的类型组合
export type ApiResponseData<T> = T extends User
? { user: T }
: T extends string
? { message: T }
: { data: T };
// 使用类型约束确保类型安全
export type Validate<T, U> = T extends U ? T : never;
构建工具集成
3.1 Webpack集成
Webpack是现代前端开发中最重要的构建工具之一。以下是一个完整的webpack配置示例:
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
module.exports = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
clean: true,
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
module: {
rules: [
{
test: /\.tsx?$/,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
],
exclude: /node_modules/,
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
}),
new ForkTsCheckerWebpackPlugin(),
],
devServer: {
static: {
directory: path.join(__dirname, 'dist'),
},
compress: true,
port: 3000,
hot: true,
},
};
3.2 Vite构建配置
Vite作为新一代构建工具,提供了更快的开发体验:
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tsconfigPaths from 'vite-tsconfig-paths';
export default defineConfig({
plugins: [
react(),
tsconfigPaths(),
],
server: {
port: 3000,
host: true,
},
build: {
outDir: 'dist',
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
utils: ['lodash', 'axios'],
},
},
},
},
css: {
modules: {
localsConvention: 'camelCase',
},
},
});
3.3 构建优化策略
为了提升构建性能,我们需要实施以下优化策略:
// 优化后的tsconfig.json配置
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"types": ["node"],
"allowJs": true,
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"removeComments": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"exactOptionalPropertyTypes": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictConstructorChecks": true,
"strictPropertyInitialization": true,
"noImplicitAny": true,
"noImplicitThis": true,
"useUnknownInCatchVariables": true,
"alwaysStrict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"exactOptionalPropertyTypes": true,
// 性能优化相关
"incremental": true,
"composite": true,
"declarationDir": "./dist/types",
"emitDeclarationOnly": true,
"isolatedModules": true,
"preserveSymlinks": true,
"noEmitOnError": true,
"noErrorTruncation": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"**/*.test.ts",
"**/*.spec.ts"
]
}
开发环境配置
4.1 IDE配置
推荐使用VS Code作为TypeScript开发环境,以下是一些重要的配置:
// .vscode/settings.json
{
"typescript.preferences.importModuleSpecifier": "relative",
"typescript.preferences.importModuleSpecifierEnding": "js",
"typescript.preferences.quoteStyle": "single",
"typescript.preferences.insertSpaceAfterFunctionKeywordForAnonymousFunctions": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
"typescript.preferences.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
评论 (0)