| name | typescript-strict |
| description | Enforce TypeScript strict mode and type safety. Use when setting up projects, reviewing code, or when type errors are ignored. Covers strict flags, no-any rules, and type inference best practices. |
| allowed-tools | Read, Glob, Grep, Edit, Write, Bash |
| license | MIT |
| metadata | {"author":"antigravity-team","version":"1.0"} |
TypeScript Strict Mode
TypeScript ์๊ฒฉ ๋ชจ๋์ ํ์
์์ ์ฑ์ ๊ฐ์ ํ๋ ์คํฌ์
๋๋ค.
2025 Context
TypeScript 5.x์์ strict ๋ชจ๋๊ฐ ์ ํ๋ก์ ํธ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๊ถ์ฅ๋จ
"any ์ฌ์ฉ์ TypeScript๋ฅผ ์ฐ๋ ์๋ฏธ๋ฅผ ์์ค๋ค"
Core Rules
| ๊ท์น | ์ํ | ์ค๋ช
|
|---|
strict: true | ๐ด ํ์ | ๋ชจ๋ ์๊ฒฉ ๊ฒ์ฌ ํ์ฑํ |
any ๊ธ์ง | ๐ด ํ์ | unknown ๋๋ ์ ๋ค๋ฆญ ์ฌ์ฉ |
// @ts-ignore ๊ธ์ง | ๐ด ํ์ | ํ์
์๋ฌ ํด๊ฒฐ ํ์ |
as ์บ์คํ
์ต์ํ | ๐ก ๊ถ์ฅ | ํ์
๊ฐ๋ ์ฐ์ |
tsconfig.json ๊ถ์ฅ ์ค์
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"exactOptionalPropertyTypes": true,
"noPropertyAccessFromIndexSignature": true
}
}
any ๊ธ์ง
๋ฌธ์ : any ์ฌ์ฉ
function processData(data: any) {
return data.value;
}
const result: any = fetchData();
result.nonExistent();
ํด๊ฒฐ: unknown ๋๋ ํ์
๋ช
์
function processData(data: unknown) {
if (isValidData(data)) {
return data.value;
}
throw new Error('Invalid data');
}
function isValidData(data: unknown): data is { value: string } {
return typeof data === 'object'
&& data !== null
&& 'value' in data;
}
function processData<T extends { value: string }>(data: T) {
return data.value;
}
any โ unknown ๋ง์ด๊ทธ๋ ์ด์
function parse(json: string): any {
return JSON.parse(json);
}
function parse(json: string): unknown {
return JSON.parse(json);
}
const result = parse('{"name": "test"}');
if (isUser(result)) {
console.log(result.name);
}
ํ์
๋จ์ธ(as) ์ต์ํ
๋ฌธ์ : ๊ณผ๋ํ ํ์
๋จ์ธ
const user = response.data as User;
user.name.toUpperCase();
const value = data as unknown as TargetType;
ํด๊ฒฐ: ํ์
๊ฐ๋ ์ฌ์ฉ
function isUser(data: unknown): data is User {
return (
typeof data === 'object' &&
data !== null &&
'name' in data &&
typeof (data as { name: unknown }).name === 'string'
);
}
if (isUser(response.data)) {
response.data.name.toUpperCase();
}
import { z } from 'zod';
const UserSchema = z.object({
name: z.string(),
email: z.string().email(),
});
const user = UserSchema.parse(response.data);
Null ์์ ์ฑ
strictNullChecks ํ์ฉ
function getLength(str: string | null) {
return str.length;
}
function getLength(str: string | null) {
if (str === null) return 0;
return str.length;
}
function getLength(str: string | null) {
return str?.length ?? 0;
}
๋ฐฐ์ด ์ธ๋ฑ์ค ์ ๊ทผ
const arr = [1, 2, 3];
const first = arr[0];
console.log(first.toFixed(2));
if (first !== undefined) {
console.log(first.toFixed(2));
}
console.log(arr[0]?.toFixed(2) ?? 'N/A');
ํจ์ ํ์
๋ฐํ ํ์
๋ช
์ (๊ถ์ฅ)
function fetchUser(id: string) {
return api.get(`/users/${id}`);
}
async function fetchUser(id: string): Promise<User> {
return api.get(`/users/${id}`);
}
ํจ์ ์ค๋ฒ๋ก๋
function process(input: string): string;
function process(input: number): number;
function process(input: string | number): string | number {
if (typeof input === 'string') {
return input.toUpperCase();
}
return input * 2;
}
const str = process('hello');
const num = process(42);
์ ๋ค๋ฆญ ํ์ฉ
function first(arr: any[]): any {
return arr[0];
}
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
ESLint ๊ท์น
{
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
],
"rules": {
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unsafe-assignment": "error",
"@typescript-eslint/no-unsafe-member-access": "error",
"@typescript-eslint/no-unsafe-call": "error",
"@typescript-eslint/no-unsafe-return": "error",
"@typescript-eslint/explicit-function-return-type": "warn",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/prefer-nullish-coalescing": "warn"
}
}
๊ธ์ง ํจํด
data as any
(data as unknown) as TargetType
data!
data as Type
Workflow
1. ์ ํ๋ก์ ํธ ์ค์
npx tsc --init
grep -n "strict" tsconfig.json
2. ๊ธฐ์กด ํ๋ก์ ํธ ๋ง์ด๊ทธ๋ ์ด์
npx tsc --noEmit
3. ์ฝ๋ ๋ฆฌ๋ทฐ ์ฒดํฌ
ํ์
์์ ์ฑ ์ฒดํฌ:
- [ ] any ์ฌ์ฉํ์ง ์์
- [ ] @ts-ignore ์์
- [ ] ํ์
๋จ์ธ ์ต์ํ
- [ ] null ์ฒดํฌ ์ ์ ํจ
Checklist
References