ืืขืจืืช ืืืืคืืกืื ืฉื TypeScript ืืืืืช ืืืืงื ืืฉืืขืืชืืช ืฉื ืืืืื ืืคื ื ืืจืฆืช ืงืื, ืื ืืชืืืืช ืืืืคืืกืื, ืืืคืืื ืื ืืกืจืื, ืืชืืืืช ืคืื ืงืฆืื ืฉืืืืืช. ืื ืฉืืื ืื ืืืืื ืืชืคืืก ืืื ืื ืืฉืืจ: ืคืืืขืืืืช ืืืืื ืฉืชืืืืืช ืืืืคื ืฉืื ื ืชืื ืื ืืืจืืื ืืจื ืืืคืืืงืฆืื, ืืคืจืืช ืืจืืืืงืืื ืืืช ืฉืืฆืืืจืืช ืืืืจื ืืื ืืื ืฉืืืืืืช ืืฆืืืช ืืืืฉืืฉืื, ืืฆืื ืืช ืฉื ืฉืืจ ืืืกืืก ืืงืื ืืื ืจื ืืืืจ ืฉืืงืืจืืื ืืื ืืืกืจื, ืืฉืืืืืช ืชืื ืืช ืืกืื ืืจืื ืืืช ืฉืืชืงืืคืืืช ืืืืื ืื ื ืืฉืืืช ืืชื ืื ืืื ืจืืฆื ืกืคืฆืืคืืื. ืืื ื ืืชืื ืกืืืืื ืืืืืื ืืช ืืคืขืจืื ืืืื, ืืืืืจืช ืืฉืืืื ืื ืืื ืชืืืื ืืื ืฉืืชื ืืืืช ืื ืกืื ืืืฆืื.
ืืืจืื ืื ืืืกื ืืช ืืืืื ืืืฉืืืื ืืฆืืืชื TypeScript ืืฉื ืช 2026: ืฉืืืช ื-linting (ESLint ืขื typescript-eslint, Biome, OxcLint), ืฉืืืช ืืืืืื (Semgrep, Snyk Code, SonarQube), ืฉืืืช ืืืืจืืืืืช (Dependency-Cruiser, Deptrac, Nx), ืฉืืืช ื-dead code (Knip) ืืฉืืืช ืื ืืชืื ืืขืืืง (ts-morph, ืืืืจ TypeScript ืขืฆืื). ืขืืืจ ืื ืืื ืืื, ืืืืฉ ืืื ืขื ืื ืฉืืื ืขืืฉื ืืคืืขื, ืืืฆื ืืืืืืจ ืืืชื, ืืืชื ืืื ืืื ื ืืืื ืืืชืืื ืืืฉืืื.
ื ืื ื ืขืืืจ ืืกืืกื ืงืื ืฉืืฃ ืืื ืื ืืืื
SMART TS XL ืืฆืืืจ ืืืืคื ืืืืืืื ืฉืื ืืืื ืฉืืืจืื ืืื ืืกืืก ืืงืื ืฉืื.
ืืื ืขืืืืื ื ืืชืื ืกืืื ืฉื TypeScript: ืืืืช ืืฉืืืื
ืืคื ื ืฉื ืฆืืื ืืืืื ืืืืืื, ืืืืื ืฉืืืื ืืืคื ืื ืืื ืืชืคืงืืื ืืขืืงืจื, ืืชืืืชื ื-CI ืืืืงืจื ืืฉืืืืฉ ืืืืืืืื ืฉืื. ืืื ืืื ืืืื ืืืืกื ืืช ืื ืืืืืื, ื ืืชืื ืืืืืช ืืขืื ืฉื TypeScript ืืืจืฉ ืฉืืืืช ืฉื ืืื.
| ืืื | ืคืื ืงืฆืื ืจืืฉืืช | ืืชืืื ื-CI | ืขืืืช | ืืื ืืื |
|---|---|---|---|---|
| ESLint + typescript-eslint | ืืื ืืืืฉื, ืกืื ืื, ืืืื ืืืืขืืช ืืกืื | ืืฉ | ืืืคืฉื | ืืืกืืืืช ืืื-ืฆืืืชืืืช, ืืืืืืช ืืกืื ืืกืื ืืจืื ื |
| ืืืืื | ืืื ืืื ื + ืขืืฆืื | ืืฉ | ืืืคืฉื | ESLint + ืชืืืืฃ ืืคื ืืืชืจ, ืืืืจืืช |
| ืืืงืกืืื ื | ืืื ืื (ืชืืื ื-ESLint) | ืืฉ | ืืืคืฉื | ืืื ืืจืคืืก ืืงืืง ืืืื ื ืกืืืื ืืืืจืื |
| ืืืืจ TypeScript (tsc) | ืกืื ืืืืงื | ืืฉ | ืืืคืฉื | ืฉืืืืืช ืืงืืื, ืืืืคื ืงืคืื ืืช ืฉื ืืฆื |
| Semgrep | SAST, ืชืื ืืืช ืืืชืืืืช ืืืฉืืช | ืืฉ | ืืื ื + ืืชืฉืืื | ืกืจืืงืช ืืืืื, ืืืื ืืจืืื ืืืชืืืื ืืืฉืืช |
| ืงืื ืกื ืืง | SAST, ืืืืืช ืชืืืช | ืืฉ | ืืื ื + ืืชืฉืืื | ืฆืืืชื ืืืืื ืืืงืื ืืจืืฉืื, ืฉืืืื IDE |
| ืกืื ืืจ ืงืืื / ืกืื ืืจ ืงืืืื | ืฉืขืจื ืืืืืช, ืืขืงื ืืืจ ืืืืืช | ืืฉ | ืืื ื + ืืชืฉืืื | ืืืืืช ืืืืื ืื ืืืืืืช ืืจืืื ืืช |
| ืกืื ืืจืืื ื | ืืฉืื ืืืืืชื ืืจืืช IDE | IDE ืืืื | ืืืคืฉื | ืจืืืื ืืืื ืื ืืืืืื ืืืืืืช |
| ืกืคืื ืช ืชืืืืืช | ืืืืคืช ืืจืฃ ืชืืืช | ืืฉ | ืืืคืฉื | ืืืืืช ืืืืื ืืืจืืืืืื |
| ืืคืืจืง | ืืืืคืช ืืืืืืช ืฉืืืืช | ืืฉ | ืืืคืฉื | ืืจืืืืงืืืจื ื ืงืืื, ืืืืืืช DDD |
| Nx | ื ืืืื ืชืืืช ืืื ืืจืคื | ืืฉ | ืืื ื + ืืชืฉืืื | ืืืืืืช ืืืืื Monorepo |
| ืืืืจื | ืงืื ืืช ืืืฆืื ืฉืืื ื ืืฉืืืืฉ | ืืฉ | ืืืคืฉื | ืฆืืฆืื ืงืื ืฉืืื ื ืืฉืืืืฉ ืืงื ื ืืืื ืืืื |
| ts-ืืืจืฃ | ื ืืชืื TS ืคืจืืืจืืื AST | ืกืืงืืืื | ืืืคืฉื | ื ืืชืื ืืืชืื ืืืฉืืช, ืงืืืืืืื, ืืื ืขืืืื |
ืฉืืื 1: ืกืืืื ืืกืื ืื
ESLint ืขื typescript-eslint
ESLint ื ืฉืืจ ืืืกืืก ืฉื ืืฆืืจืช ืคืชืจืื ืืช ืืืฆืืจืช ืคืชืจืื ืืช ื-TypeScript. ืขื ื- typescript-eslint ืืืืืื, ืืื ืืงืืืช ืืืฉื ืืืืืข ืืกืื ืฉื TypeScript ืืืืืื ืืืืืฃ ืืืืื ืืืืจืฉืื ืืงืฉืจ ืกืืืื, ืืืฉืจ ืืืฉืืืื ืฉืืื ืื ืืืืืื ืืกืคืฆืืคืืื ืืืกืื ืืจืื ืืื ืฉืชืืคืกืื ืืขืืืืช ื ืคืืฆืืช ืฉื Promise.
ืืืืื
npm install --save-dev typescript-eslint
JavaScript
// eslint.config.js
import tseslint from "typescript-eslint";
export default tseslint.config(
...tseslint.configs.strictTypeChecked,
{
languageOptions: {
parserOptions: {
project: true,
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
// Async safety rules -- highest value TypeScript-specific rules
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/require-await": "warn",
// Type safety
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unsafe-assignment": "error",
"@typescript-eslint/no-unsafe-return": "error",
},
}
);
ืืจืืขืช ืืืืืื ืืืกืื ืืจืื ืืื ืืขืื ืื ืืชืืกืคืช ืืขืืช ืืขืจื ืืืืื ืืืืชืจ ืฉ-typescript-eslint ืืกืคืง ืขื ืคื ื ESLint ืจืืื. ืื ืชืืคืกืื: ืืืืืืช ืื ืืืืคืืืช (ืืืืืืช ืฆืคืืช), await ืืืื ืขื ืขืจืืื ืฉืืื ื Promise, Promises ืืืืขืืจืื ืืงืจืืืืช ืืืืจืืช ืืืฆืคืืช ืืคืื ืงืฆืืืช ืกืื ืืจืื ืืืช, ืืคืื ืงืฆืืืช ืืกืื ืืจืื ืืืช ืฉืืขืืื ืื ืืฉืชืืฉืืช awaitืืื ืื ืชืื ืืืช ืฉืืชืงืืคืืืช ืืฆืืจื ื ืงืืื ืื ืืืืฆืจืืช ืืฉืืื ืืืื ืจืืฆื ืืชื ืืื ืกืคืฆืืคืืื.
ืื ืฉ-ESLint ืื ืืืื ืืขืฉืืช : ื ืืชืื ืืจืืืช ื ืชืื ืื ืืื ืงืืฆืื, ืืืืคืช ืืืืืืช ืืืจืืืืืื, ืืขืงื ืืืจ ืืชืื ืืืืื ืื ืืืืื ืืืฆืื ืืช. ืขืืืจ ืืื, ื ืืจืฉืืช ืืฉืืืืช ืืืืจืืช ืฉืืืื.
ืืืืื: ESLint ืืืืืจื ื + ืชืืืืฃ ืืคื ืืืชืจ
Biome ืืืืืฃ ืื ืืช ESLint ืืื ืืช Prettier ืืงืืืฅ ืืื ืืจื ืืืื ืืืืกืก Rust ืฉืคืืขื ืืืจ ืืืชืจ ืคื 25-35. ืืื ืชืืื ื-JavaScript, TypeScript, JSX ื-JSON. ืขืืืจ ืคืจืืืงืืื ืืืฉืื ืื ืฆืืืชืื ืืืชืืกืืืื ืืืืจืืืืช ืืชืืกืคืื ืฉื ESLint ืืืืฆืืขืื ืืืืืื ืืืกืืกื ืงืื ืืืืืื, Biome ืืื ืืืืืจื ืืืื ืืืืืจื ืืช ืืืืงื ืืืืชืจ.
ืืืืื
npm install --save-dev --save-exact @biomejs/biome
npx @biomejs/biome init
ืืืืื
# Check and format in one pass
npx @biomejs/biome check --write src/
# CI mode -- no modifications, exit non-zero on any finding
npx @biomejs/biome ci src/
ืืขืจืืช ืืชืืกืคืื ืฉื Biome ืงืื ื ืืืชืจ ืืื ืฉื ESLint, ืืืจ ืฉืืฉืื ืืฆืืืชืื ืขื ืืืืื ืืืชืืืื ืืืฉืืช ื ืจืืืื ืื ืชืืกืคืื ืกืคืฆืืคืืื ืืืกืืจืช. ืขืืืจ ืฆืืืชืื ืืืฉืชืืฉืื ืจืง ืืืืื ืืืืื ืฉื ESLint ืืืขืืฆืื Prettier, Biome ืืกืคืง ืืืกืื ืฉืืื ืขืจื ืืืืงืืง ืืืื ืืืืฆืืข.
OxcLint: ืชืืืืืช ESLint ืขื ืืืืจืืช ืจืืฉืื ื
OxcLint (ืืืง ืืคืจืืืงื Oxc) ืืจืืฅ ืืืืื ืชืืืื ESLint ืืืืืจืืช ืืืฆืืข ืืืืจื ืคื 50-100. ืืื ืืื ื ืืืืืฃ ืืช ืืืขืจืืช ืืืงืืืืืืช ืืืืื ืฉื ESLint, ืื ืืฉืืฉ ืืืคืฉืจืืช ืืืืืจื ืืืืชืจ ืขืืืจ ืฆืื ืืจืืช CI ืฉืืื ืืื ื-lint ืืื ืฆืืืืจ ืืงืืืง.
ืืืืื
npm install --save-dev oxlint
npx oxlint src/
OxcLint ืืื ืืืืืจื ืื ืืื ื ืขืืืจ ืืื ืืจืคื ืืืืืื ืฉืืื ESLint ืกืื ืืจืื ืืืงื ืืงืืช ืกืคืืจืืช ืืืฉืืืืช ืืืืืช ืืืฉืื ืืคืืืชื ืืช ืืืืืช ืืงืฉืช ื-pull. ืืื ืขืืื ืืฆืืจื ืืืืื ืืืืชืจ ืืฆื ESLint ืืืงืื ืืืืืืฃ ืืืชื, ืืคืขื ืืช OxcLint ืขืืืจ ื ืชืื ืืืฉืื ืืืืืจ ืืืช ESLint ืขืืืจ ืืืกืื ืืื ืฉื ืืืืืื ืืฉืขืจ ืืจืื-ืืืืืื.
ืฉืืื 2: ืืืืงืช ืกืืืื, ืืืืจ TypeScript
ืืืืจ TypeScript (tsc) ืืื ื ืจืง ืืื ืื ืืื, ืืื ืื ืืข ืื ืืชืื ืืกืืื ืืขืืงืจื ืืชืงืื ืืช ืืจืืช ืืกืื. ืืคืขืืช ืืฆื strict ืืคืขืืื ืืช ืืืืืจืืช ืฉืชืืคืกืืช ืืช ืจืื ืืืืืื ืืขืืื ืืืืืชื:
ื'ืกืื
{
"compilerOptions": {
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"exactOptionalPropertyTypes": true,
"useUnknownInCatchVariables": true
}
}
ืืืืื
# Type-check only, no emit -- ideal for CI
npx tsc --noEmit
noUnusedLocals ื noUnusedParameters ืืจืืช ืืืืืจ, ืืชืคืืก ืืฉืชื ืื ืืคืจืืืจื ืคืื ืงืฆืื ืฉืืื ื ืืฉืืืืฉ. useUnknownInCatchVariables (ืกืืื TypeScript 4.4+) ื ืชืคืกื ืืจืืืื ื unknown ืืื any, ืืืคื ืฆืืฆืื ืกืืืื ืืคืืจืฉ ืืคื ื ืืฉืืืืฉ.
ื ืืชืื ืืจืืืช ืืงืจื ืฉื TypeScript ืืื ืืืืืช ืืืื ืืช ืฉืืืืืจ ืืกืคืง ืืฆืืฆืื ืกืืืื ืืชืื ืขื ืคืื ืืืชื ืื. ืื ืื ืืื ื ืคืจื, ืืืืคืฉืจ strict ืืฆื ืืืืื ืฉืืื ืืืืฉื ืืงืคืื ืืช ืืืื. ื ืืชืื ืืจืืืช ืืืงืจื ืฉื ืืืืืจ ืืืื ืกืืืื ืืื ืื, typeof ืฆ'ืงืื, instanceof, ืืืคืืกื ืืืืืืื ืืงืฆืืขืืื ืืคืืื.
ืืืืืช tsc : ืืืืจ TypeScript ืืื ื ืืืฆื ืคืืืขืืืืช ืืืืื, ืืคืจืืช ืืืืืืช ืืจืืืืงืืื ืืืช ืื ืืืฆืื ืืช. ืืื ืืืฆื ืฉืืืืืช ืืงืืื, ืืืื ืขืืฉื ืืืช ืืืืคื ืื ืืฉืืขื.
ืฉืืื 3: ืืืืื, SAST ืขืืืจ TypeScript
Semgrep: ืกืจืืงืช ืืืืื ืืืืกืกืช ืชืื ืืืช
Semgrep ืืืฆืืช ืคืืืขืืืืช ืืืืื ืืืืฆืขืืช ืืชืืืช ืชืื ืืืช ืงืื. ืขืืืจ TypeScript, ืืื ืืืื ืืืืืช ืืืจืงืช SQL, XSS, ืืืฉืืจืื ืืงืืืืื, ืืืืืืงืืื ืื ืืืืืื. eval ืฉืืืืฉ, ืืืืื ืื ืืืคืืก ืืชืฆืืจืืช Express.js ืื ืืืืืืืืช, ืชืื ืืืช ืฉืืชืงืืคืืืช ืืืืื ืื ืืฆืืืืช ืคืืืขืืืืช ืื ืืชื ืืช ืื ืืฆืื.
ืืืื
# Custom rule: flag user input in SQL queries (TypeScript)
rules:
- id: ts-sql-injection-risk
patterns:
- pattern: |
const query = `SELECT ... ${$USER_INPUT} ...`;
message: "User input directly interpolated into SQL -- use parameterized queries"
languages: [typescript]
severity: ERROR
ืืืืื
# Run with the community TypeScript security rules
semgrep scan --config=p/typescript --config=p/owasp-top-ten src/
Semgrep ืืฉืืื ืืช ESLint, ืื ืืชืืจื ืืืชื. ESLint ืืืืฃ ืืืกืืืืช; Semgrep ืืืฆื ืชืื ืืืช ืื ืื-ืืืืื. ืจืื ืฆืืืชื TypeScript ืฉืืืคืช ืืื ืืืืืื ืฆืจืืืื ืืืจืืฅ ืืช ืฉื ืืื.
ืงืื Snyk: SAST ืืืืกืก ML ืขื ืฉืืืื IDE
Snyk Code ืืืฆืขืช SAST ืขื ืื ืืข ื ืืชืื ืืืืกืก ืืืืืช ืืืื ื ืฉืขืืงื ืืืจ ืืจืืืืช ืืืืื ืืื ืงืืฆืื. ืืื ืืฉืชืืืช ื-VS Code ืื-JetBrains IDEs, ืืืืฉืคืช ืืืฆืืื ืืืืคื ืืงืืื ืืืฉืจ ืืคืชืืื ืืืชืืื ืงืื ืืืงืื ืืืืชืื ืืืจืฆืช CI.
ืืืืื
npm install --save-dev snyk
npx snyk auth
npx snyk code test
ืืืืงืื ืฉื Snyk Code ืืืืืืืช ืืืคืชืืื, ืืฉืื ืืืื ื ืขื IDE, ืืฆืขืืช ืชืืงืื ืื ืืฆื ืื ืืืฆื ืืืืืืืืช ืืชืืงืื, ืืืคืืื ืืืชื ืืืืืจื ืืืื ืืืชืจ ืืืฉืจ ืืื ืื ืืืืืื ืืฉืื ืื ืคืืืช ืืืืืื ืืืืื.
SonarQube ื-SonarLint: ืฉืขืจื ืืืืืช ืืืขืงื ืืืจ ืืืืืช
SonarQube ืืกืคืง ื ืืชืื ืจืฆืืฃ ืฉื ืืืืืช ืืงืื ืืืืฆืขืืช ืืื ืืืืื ืื, ืืขืงื ืืืจ ืืืืืช ืืงืืฉืื ืืงืฉืืช ืืฉืืื. ืขืืืจ TypeScript, ืืื ืืืื ืืืืื, ืจืืืืช ืงืื, ื ืงืืืืช ืืืืช ืฉื ืืืืื ืืืคืืืืืืช. SonarLint ืืื ืืจืืืช IDE ืฉืืืฉืคืช ืืช ืืืื SonarQube ืืืืคื ืืงืืื.
ืขืืืจ ืฆืืืชื TypeScript, SonarCloud (ืืืจืกื ืืืืืืกื ืช ืืขื ื) ืืื ืื ืชืื ืืคืฉืื ืืืชืจ: ืืื ืื ืขืืืจ ืืืืจืื ืฆืืืืจืืื, ืขื ืฉืืืื CI ืืจื GitHub Actions ืื GitLab CI ืชืื ืืงืืช.
ืืืื
# .github/workflows/sonar.yml
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
ืืขืจื ืืขืืงืจื ืฉื SonarQube ืขื ืคื ื ืขืืืื ืฉืืื ืืืืืืื (raw linting) ืืื ืืืื ืืืืื ืฉืื: ืืืฆื ืืืืืช ืืงืื ืืชืคืชืืช ืืืืจื ืืื, ืืืื ืจืืืืื ืืชืืจืืจืื, ืืืื ืฆืืื ืฉืขืจ ืืืืืืช ืฉื ืงืื ืืืฉ ืขืืืจ ืื ืืงืฉืช ืืฉืืื. ืืืืื ืืื ืืคืื ืื ืื ืืืื ืื ืื ืฉ-SonarQube ืขืืฉื ืฉ-ESLint ื-Semgrep ืื ืืืืืื ืืขืฉืืช.
ืฉืืื 4: ื ืืชืื ืืืจืืืื
Dependency-Cruiser: ืืืืคืช ืืืื ืืืื ืืืืื
Dependency-Cruiser ืืืืช ืฉืืืจืฃ ืืืืืืื ืฉืื ืขืืื ืืืืืื ืืจืืืืงืืื ืืื ืืืืืจืื. ืืื ืืืืฆืจ ืืจืคื ืชืืืช ืืืืชืืื ืืืืฉื ื-CI ืืืฉืจ ืืงืื ืืคืจ ืืช ืืืืืฆื ืืืืืืช ืืืืืื.
JavaScript
// .dependency-cruiser.cjs
module.exports = {
forbidden: [
{
name: "no-circular",
severity: "error",
comment: "Circular dependencies make code hard to test and maintain",
from: {},
to: { circular: true },
},
{
name: "no-ui-in-domain",
severity: "error",
comment: "Domain modules must not import from UI layer",
from: { path: "^src/domain" },
to: { path: "^src/ui" },
},
{
name: "no-external-in-shared",
severity: "warn",
comment: "Shared utilities should minimize external dependencies",
from: { path: "^src/shared" },
to: { pathNot: "^(src|node_modules/(lodash|date-fns))" },
},
],
};
ืืืืื
npx depcruise --validate .dependency-cruiser.cjs src/
Dependency-Cruiser ืืืคื ืืฉืืจืืช ืืฉืืืืชืืช "react dependency analysis cli tool" ืื ืชืื ื Search Console, ืืื ืืืื ืืกืื ืืจืื ืืืฆืืจื ืืืืืืช ืฉื ืืจืคื ืชืืืช ืืคืจืืืงืืื ืฉื TypeScript/React.
ืืคืืจืง: ืืืืคืช ืืืืืืช ืืืืกืกืช ืฉืืืืช
Deptrac ืืืืฃ ืฉืืืืช ืืืจืืืืืืช, ืืืืืื ืฉืงืื persistence ืื ืืืื ืืืืื ืืืืฆืืช, ืฉืืืืืืงืื ืชืืื ืืื ื ืชืืืืื ืืชืฉืชืืช, ืืฉืืืืืืช ืืืืืืืื ืืืืืืื ืืืืจื ืื ืืกืืก ืืงืื.
ืืืื
# deptrac.yaml
parameters:
layers:
- name: Domain
collectors:
- type: directory
value: src/domain
- name: Application
collectors:
- type: directory
value: src/application
- name: Infrastructure
collectors:
- type: directory
value: src/infrastructure
ruleset:
Domain:
- ~Infrastructure # Domain must not depend on Infrastructure
Application:
- Domain
Infrastructure:
- Application
- Domain
Deptrac ืืื ืืขื ืขืจื ืจื ืืืืชืจ ืืคืจืืืงืืื ืืขืืงืืื ืืืจ ืชืื ืืืช ืฉื ืืจืืืืงืืืจื ื ืงืืื, DDD ืื ืืจืืืืงืืืจื ืืฉืืฉื, ืฉืืื ืืืืื ืฉืืืืช ืืื ืืืืืฅ ืขืืฆืืื, ืื ืจืง ืืขืืคื.
Nx: ื ืืืื ืชืืืช ืืจืืช Monorepo
ืขืืืจ ืืื ื-ืจืคืืืื ืฉื TypeScript, Nx ืืกืคืงืช ืืืืคืช ืืืืืืช ืืืืืืื, ืืืืื ืื ืืื ืืืฉืคืขืช, ืืืืืื ืฉื ืืจืฃ ืชืืืืืช ืืื ืืคืจืืืงืืื ืืืืืจ.
ื'ืกืื
// .eslintrc.json -- Nx module boundary rules
{
"rules": {
"@nx/enforce-module-boundaries": [
"error",
{
"allow": [],
"depConstraints": [
{ "sourceTag": "scope:shared", "onlyDependOnLibsWithTags": ["scope:shared"] },
{ "sourceTag": "scope:feature", "onlyDependOnLibsWithTags": ["scope:shared", "scope:feature"] },
{ "sourceTag": "scope:app", "onlyDependOnLibsWithTags": ["scope:shared", "scope:feature"] }
]
}
]
}
}
Nx's affected ืคืงืืืืช ืืจืืฆืืช ืจืง ืืช ืืืืืงืืช ืื-linting ืืจืืืื ืืืื ืืืืืืืื ืฉืืฉืชื ื, ืื ืฉืืคืืืช ืืฉืืขืืชืืช ืืช ืืื ื-CI ืืืื ืืจืคื ืืืืืื.
ืฉืืื 5: ืืืืื ืงืื ืืช
Knip: ืืฆื ืงืืฆื ืืืฆืื, ืงืืฆืื ืืชืืืืืช ืฉืืื ื ืืฉืืืืฉ
Knip ืื ืชื ืืช ืืจืฃ ืืืืืื ืืืื ืืื ืืืืืช ืืืฆืื ืฉืืื ื ืืฉืืืืฉ, ืงืืฆืื ืฉืืื ื ืืฉืืืืฉ ืืงืืฆืื ืฉืืื ื ืืฉืืืืฉ package.json ืชืืืืืช, ืกืื ืฆืืืจืช ืืงืื ืฉ-ESLint no-unused-vars ืื ืืืื ืืชืคืืก ืื ืื ืืืคืฉ ืจืง ืืชืื ืงืืืฅ.
ืืืืื
npm install --save-dev knip
npx knip
ื'ืกืื
// knip.json
{
"entry": ["src/index.ts", "src/**/*.test.ts"],
"project": ["src/**/*.ts"],
"ignore": ["src/generated/**"],
"ignoreDependencies": ["vitest"]
}
Knip ืืชืืฆืข ืืฉืืจืืช ืื ืชืื ื SC ืืชืืจ "dead code detection unused exports javascript typescript". ืืื ืืืื ืืืขืื ืืืืชืจ ืืืื ืืืืืื ืงืื ืืช ืืจืืช ืืืืืื ืืคืจืืืงืืื ืฉื TypeScript.
ืฉืืื 6: ื ืืชืื ืคืจืืืจืืื, ts-morph
ts-morph ืืื ืขืืืคืช API ืฉื ืืืืจ TypeScript ืืืืคืฉืจืช ืืชืืืช ื ืืชืืืื ืืืชืืืื ืืืฉืืช, ืงืืืืืืื ืืืืื ืื ืื AST ืฉื TypeScript. ืืื ืืืคืฉ ืืฉืืจืืช ืื ืชืื ื SC ื-"ts-morph" ื-"ts morph".
ืืชื ืืชืืื
import { Project } from "ts-morph";
const project = new Project({ tsConfigFilePath: "tsconfig.json" });
// Find all async functions that never await anything
const suspiciousAsyncFns: string[] = [];
for (const sourceFile of project.getSourceFiles()) {
for (const fn of sourceFile.getFunctions()) {
if (fn.isAsync()) {
const hasAwait = fn.getDescendantsOfKind(
SyntaxKind.AwaitExpression
).length > 0;
if (!hasAwait) {
suspiciousAsyncFns.push(
`${sourceFile.getFilePath()}:${fn.getName() ?? "anonymous"}`
);
}
}
}
}
console.log("Async functions with no await:", suspiciousAsyncFns);
ts-morph ืืื ื ืืื ื ืืชืื ืืืื ืืืคืขืื, ืืื ืืกืคืจืืื ืฉืื ืืฉืชืืฉืื ืืื ืืื ืืช ืืื. ืืื ืืชืืื ืืฆืืืชืื ืืืงืืงืื ืื ืืชืื ืืืชืื ืืืฉืืช ืืขืืจ ืืื ืฉืืืืื ืืงืืืืื ืชืืืืื ืื: ืกืงืจืืคืืื ืฉื ืืืืจื, ืืืืชืื ืืจืืืืงืืื ืืื ืืืชืืืื ืืืฉืืช, ืฉืืคืืฅ ืืืืืืื ืื ืฆืื ืืจืืช ืืฆืืจืช ืงืื.
ื ืืชืื ืกืืื ืืกืื ืืจืื ื/ืืืชื ื ืฉื TypeScript
ื ืชืื ื Search Console ืืฆืืืื ืืฉืืื ืกืคืฆืืคื ืฉื ืฉืืืืชืืช ืกืืื "typescript static analysis async await paper tool" ื-"typescript static analysis async await vulnerability paper tool". ืืื ืืฉืงืคืื ืืืืืื ืืืืคืฉืื ืืืื ืฉืืืื ืื ืฉืืืืืช ืชืื ืืช ืืกืื ืืจืื ืืืช ืืจืืช ืืกืื.
ืืชืฉืืื ืืืขืฉืืช ืขืืืจ ืฆืืืชื TypeScript ืืืืฆืืจ ืืื ืืจืืขืช ืืืืืื ืืกืคืฆืืคืืื ืืืกืื ืืจืื ืืื ืฉื typescript-eslint (no-floating-promises, await-thenable, no-misused-promises, require-await) ืืฉืืืื ืขื strictNullChecks ื useUnknownInCatchVariablesืืื, ืืื ืืืืืื ืืช ืฉืืืืืช ืืืกืื ืืจืื ืืืช ืื ืคืืฆืืช ืืืืชืจ ืืืื ืืืืืงืง ืืืื ืืืงืจ ืืงืืืืื.
ืขืืืจ ืฆืืืชืื ืฉืขืืกืงืื ืืืืงืจ ืืืืื ืขื ืืคืืกื ืคืืืขืืืืช ืืกืื ืืจืื ืืืช, TAJS ื-Jelly ืื ืื ืชืืื ืกืืืืื ืืงืืืืื ืืืืืืื ืืช ืืกืื ืืืงื ืฉื ืืืฆืืข ืืกืื ืืจืื ื ืฉื JavaScript, ืื ืื ืืื ืืืงืจ, ืื ืืื ืคืืชืื ืืืฆืืจ.
Angular ื-React: ื ืืชืื ืกืืื ืกืคืฆืืคื ืืืกืืจืช
ืขืืืจ ืฆืืืชื ืื ืืืืจ, @angular-eslint ืืกืคืง ืืืื linting ืกืคืฆืืคืืื ื-Angular ืืืืกืื ืชืื ืืืช ืจืืืืื, ื ืืชืื ืชืื ืืืช ืืืืจืงืช ืฉืืจืืชืื. ืืื ืืฉืชืื ืขื ืชืฆืืจืช ESLint + typescript-eslint ืืขืื.
ืขืืืจ ืฆืืืชื ืจืืืงื, ื eslint-plugin-react, eslint-plugin-react-hooks, ื eslint-plugin-jsx-a11y ืชืืกืคืื ืืืกืื ืชืื ืืืช ืกืคืฆืืคืืืช ื-React. Dependency-Cruiser ืืืคื ืื ืืชืื ืืจืคื ืชืืืืืช ืกืคืฆืืคืืื ื-React ืืืื ืืืื ืฉืขืืื ืืืืืจื ืฉืืืืชืืช "react dependency analysis cli tool" ืื ืชืื ื SC.
ืฉืืืื IDE: ืืืื ืขืืืจ VS Code ื-JetBrains
ืืฉืืืืชืืช "ืืื ืงืื ืืืืืชืืื ืืฉืืืื VS Code" ื"ืืื ืงืื ืืืืืชืืื ืืฉืืืื IDE" ืืฉืงืคืืช ืฆืืจื ืืืืชื: ืืฉืื CI ืืืืข ืืืืืจ ืืื ืืื ืืฉื ืืช ืืชื ืืืืช. ื ืืชืื ืืฉืืื IDE ืืกืคืง ืืช ืืืืืช ืืืฉืื ืืืืืงื ืืืืชืจ.
ืงืื VS : ืืจืืืช ESLint ืขื ืื ืชื ืืืืื Clippy parity, ืืจืืืช SonarLint ืขืืืจ ืืืื SonarQube ืืืืืขืื, ืืจืืืช Snyk ืขืืืจ ืืืฆืื ืืืืื, ืืฉืืจืืช ืฉืคืช TypeScript ืืืื ื ืขืืืจ ืืฉืื ืืจืืช ืืกืื.
JetBrains (WebStorm/IntelliJ) : WebStorm ืืืืข ืขื ืชืืืื ืืืื ืืช ื-TypeScript ืฉืืืฉืคืช ืฉืืืืืช ืืงืืื ืืืืคื ืืงืืื, ืื ืืกืฃ ืืืื ืืืจืฆืื ืขื ESLint, Prettier ื-SonarLint. ืืขืจืืช ืืืืืงื ืืืืื ืืช ืืืกื ืจืืืช ืืืืชื ืชืื ืืืช ืืื ืืืื ESLint.
ืชืฆืืจืช VS Code ืืืืกืื ื ืืชืื ืกืืื ืืงืกืืืื ืฉื TypeScript :
ื'ืกืื
// .vscode/settings.json
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.validate": ["javascript", "typescript", "typescriptreact"],
"sonarlint.connectedMode.project": {
"connectionId": "my-sonarcloud",
"projectKey": "my-org_my-project"
}
}
ืืื SMART TS XL ืืจืืื ืืช ื ืืชืื TypeScript ืืจืืื ืืืจืืื
ืืืืื ืื "ื ืืืกืื ืืช TypeScript ืืชืื ืคืจืืืงื TypeScript. ืืืจืืื ืื ืฉืืื ืฉืืจืืชื TypeScript ืืงืืืืื ืืื ืืจืืงืฆืื ืขื ืชืืื ืืืช ืืฆืืื ืฉื COBOL, ืืืฉืงื API ืฉื Java, ืฆืื ืืจืืช ื ืชืื ืื ืฉื Python ืื ืืขืจืืืช ืืืื ืคืจืืื ืืืืจ ืงืืื, ืืืื ืืฉืคื ืืืช ืืื ื ืืืืืื ืืจืืืช ืืช ืืชืืืืืช ืืืืฆืืช ืืืืืืช ืฉืคื.
SMART TS XL"S ื ืืชืื ืงืื ืกืืื ืืืกื ืืช TypeScript ืืฆื ืื ืฉืคื ืืืจืช ืืกืืืืช ืืืจืืื, COBOL, JCL, Java, Python, RPG, SQL, ืืืื ื ืืืื ืชืืืช ืืืืื ืขื ืคื ื ืืืื. ืืืฉืจ ืฉืืจืืช TypeScript ืงืืจื ื-API ืืืืืื ืขื ืืื ืชืืื ืืช COBOL, SMART TS XL ืืืื ืืขืงืื ืืืจ ืืงืฉืจ ืืื ืืืืืื ืืืชื ื ื ืืชืื ืืฉืคืขืืช ืืคื ื ืืืฆืืข ืื ืฉืื ืื ืืืื ืืจืืืืื.
ืืืืืช ืืืืคืืฉ ืืืจืืื ื ืืืคืืช ืืช ืื ืืกืืก ืืงืื ืืจื-ืืฉืื ื ืื ืืชื ืืฉืืืืชื: ืืฆื ืื ืืืืื โโTypeScript ืฉื ืืืืื ืกืคืฆืืคื, ืื ืฉืืืช Java ืฉืฉืืจืืช TypeScript ืงืืจื ืื, ืื ืกืคืจ ืขืืชืงืื ืฉื COBOL ืฉืืืื ื ืชืื ืื ื-API ืื ืฆืจื ืขื ืืื TypeScript, ืชืื ืฉื ืืืช, ืขื ืคื ื ืืืืืื ื ืฉืืจืืช ืงืื ืืื ืฉืืืื ืฉื ืฉืคืืช.
ืขืืืจ ืฆืืืชื ืืจืืื ืืืคืขืืืื ืืช TypeScript ืืฉืคื ืืืช ืืชืื ืชืืง ืขืืืืืช ืืืื ืืืชืจ, SMART TS XL ืืกืคืง ืืช ืื ืจืืืช ืืืืจืืืืืช ืืืช ืืืืฉื ืืืืฆื ืืฉืื ืืช ืืืคืื ืชืืืช ืฉืืืจื ืืืื TypeScript ืกืคืฆืืคืืื ืืืกืชืื ืขื ืืืืง ืฉืืื ืืืขืจืืช ืืืื SMART TS XL ืจืืื ืืช ืืฉืื.
ืื ืืืช ืืขืจืืื ืื ืืื ื
ืืื ืืื ืืืื ืืืืกื ืืช ืื ืืืื ืืืืืืช ืขืืืจ TypeScript. ืืืืฉื ืื ืืื ื ืืื ืืืฉื ืจื-ืฉืืืชืืช, ืืืฉืจ ืื ืฉืืื ืืืืื ืช ืืกืื ืืขืื ื ืคืจื:
ืขืจืืื ืืื ืืืืืช ืืคืฉืจืืช (ืคืจืืืงื ืืืฉ, ืฆืืืช ืงืื):
- ืืฆื ืงืคืื ื ืฉื TypeScript
- ESLint ืขื ืืืื ืืกืื ืืจืื ืฉื typescript-eslint
npm auditืขืืืจ ืคืืืขืืืืช ืชืืืช
ืืืกื ืืช ืืืฉืืื ืืืฆืืจ (ืฆืืืช ืืื ืื ื, ืืืืข ืืืืืื):
- ืืื ืืืขืื, ืคืืืก:
- ืืืืื ืื ืืคื ืืืชืจ ืืขืืฆืื
- Semgrep ืขืืืจ SAST ืืืืื
- ืกืืื ืืงืื ืืช
- SonarCloud ืื ืจืืืช ืืืืืช ืืืืืชืืช
ืืืกื ืืช ืืจืืื ืืช / ืืื ืืจืคื (ืฆืืืช ืืืื, ืืืืืฆืื ืืจืืืืงืืื ืืื):
- ืืื ืืืขืื, ืคืืืก:
- Dependency-Cruiser ืืืืืคืช ืืืืืืช ืืืืืืื
- Nx ืขืืืจ ืืืคืืืืืืฆืื ืฉื ืื ืืืช ืืืฉืคืขืช ืืืื ื-ืจืคื
- Deptrac ืืืืืืช ืืืืืืช ืฉืืื
- SonarQube (ืืืกืื ืขืฆืื) ืืฉืขืจืื ืืืืืชืืื ืืืชืจ
ืืืกื ืืช ืืจืืื ืืช ืฉื Polyglot (TypeScript ืืฆื ืืขืจืืืช ืืืืจ ืงืืื):
- ืืื ืืืขืื, ืคืืืก:
- SMART TS XL ืื ืืชืื ืืฉืคืขืืช ืืืฆืืช-ืืฉืื ืืช ืืืืคืื ืชืืืช


