スキル一覧に戻る
djankies

avoiding-non-null-assertions

by djankies

0🍴 0📅 2025年11月25日
GitHubで見るManusで実行

SKILL.md


name: avoiding-non-null-assertions description: Avoid non-null assertion operator (!) and use type-safe alternatives instead

Avoiding Non-Null Assertions

The non-null assertion operator (!) is deprecated in modern TypeScript because it bypasses type safety and can lead to runtime errors.

Why Avoid !

  • Bypasses type safety: Tells TypeScript "trust me" without verification
  • Runtime errors: Can cause undefined or null errors at runtime
  • Maintenance burden: Makes refactoring dangerous
  • No protection: Removes TypeScript's main benefit

Modern Alternatives

1. Optional Chaining (?.)

Bad:

const userName = user!.profile!.name;

Good:

const userName = user?.profile?.name;

2. Nullish Coalescing (??)

Bad:

const value = config!.timeout;

Good:

const value = config?.timeout ?? 5000;

3. Type Guards

Bad:

function processUser(user: User | null) {
  console.log(user!.name);
}

Good:

function processUser(user: User | null) {
  if (user !== null) {
    console.log(user.name);
  }
}

4. Early Return Pattern

Bad:

function getUserEmail(userId: number): string {
  const user = findUser(userId);
  return user!.email;
}

Good:

function getUserEmail(userId: number): string | null {
  const user = findUser(userId);
  if (!user) {
    return null;
  }
  return user.email;
}

5. Custom Type Guards

Bad:

function handleValue(value: unknown) {
  return (value as User)!.name;
}

Good:

function isUser(value: unknown): value is User {
  return typeof value === 'object' && value !== null && 'name' in value;
}

function handleValue(value: unknown) {
  if (isUser(value)) {
    return value.name;
  }
  throw new Error('Invalid user');
}

6. Narrowing with in Operator

Bad:

function process(obj: { data?: string }) {
  console.log(obj.data!.toUpperCase());
}

Good:

function process(obj: { data?: string }) {
  if ('data' in obj && obj.data !== undefined) {
    console.log(obj.data.toUpperCase());
  }
}

7. Array Methods with Type Safety

Bad:

const users: User[] = getUsers();
const firstUser = users[0]!;

Good:

const users: User[] = getUsers();
const firstUser = users.at(0);
if (firstUser) {
  console.log(firstUser.name);
}

8. Assertion Functions (TypeScript 3.7+)

Good:

function assertIsDefined<T>(value: T): asserts value is NonNullable<T> {
  if (value === undefined || value === null) {
    throw new Error('Value must be defined');
  }
}

function process(value: string | null) {
  assertIsDefined(value);
  console.log(value.toUpperCase());
}

DOM Element Access

Bad:

const button = document.getElementById('submit')!;
button.addEventListener('click', handler);

Good:

const button = document.getElementById('submit');
if (button) {
  button.addEventListener('click', handler);
}

Or with assertion function:

function assertElement<T extends Element>(
  element: T | null,
  selector: string
): asserts element is T {
  if (!element) {
    throw new Error(`Element not found: ${selector}`);
  }
}

const button = document.getElementById('submit');
assertElement(button, '#submit');
button.addEventListener('click', handler);

When Is ! Acceptable?

Only in very rare cases where:

  1. You have exhaustively verified the value exists
  2. There's no other way to express it to TypeScript
  3. You document WHY it's safe

Even then, prefer assertion functions over !.

Migration Strategy

  1. Search for all uses of ! in codebase
  2. Categorize by pattern (DOM access, array indexing, etc.)
  3. Replace with appropriate type-safe alternative
  4. Test thoroughly after each replacement
  5. Enable linting to prevent future uses

Compiler Configuration

Enable strict checks:

{
  "compilerOptions": {
    "strict": true,
    "strictNullChecks": true,
    "noUncheckedIndexedAccess": true
  }
}

Summary

Never use ! operator:

  • Use ?. for optional chaining
  • Use ?? for default values
  • Use type guards for narrowing
  • Use assertion functions when validation is needed
  • Let TypeScript protect you from null/undefined errors

スコア

総合スコア

60/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です