mcpField
A
avoid-wrapper-types

avoid-wrapper-types

github.com/marius-townhouse開発643 回インストール38 週間前に更新
リポジトリ

avoid-wrapper-types について

`string`や`number`などのプリミティブ型をオブジェクトラッパー型より使う理由を解説するTypeScript向けスキルです。型の不一致や実行時の予期しない挙動を避けるのに役立ちます。

主な機能

  1. 01小文字のプリミティブ型を使用
  2. 02ラッパー型との不一致を特定
  3. 03オブジェクト同一性と真偽値の注意点
  4. 04オートボクシングによるメソッド利用

活用シーン

  1. 01TypeScriptのプリミティブ値の型付け
  2. 02ラッパー型からの代入エラーの調査
  3. 03意図しないラッパーオブジェクトの確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/marius-townhouse/effective-typescript-skills --skill avoid-wrapper-types

インストール後、Claude Code で/avoid-wrapper-typesを入力して読み込まれたか確認します。

詳細

オブジェクトラッパー型(String、Number、Boolean、Symbol、BigInt)を避ける

概要

小文字のプリミティブ型を使用し、大文字のラッパー型は決して使用しないでください。

JavaScript にはプリミティブ型(string、number、boolean)とオブジェクトラッパー型(String、Number、Boolean)があります。TypeScript には両方の型がありますが、ラッパー型はほとんど使用しないでください。

このスキルを使う場面

  • プリミティブ値に型を付けるとき
  • ラッパー型の不一致に関するエラーが表示されたとき
  • String !== string である理由を理解するとき
  • プリミティブ型のメソッドを扱うとき

絶対に守るルール

ALWAYS use lowercase: string, number, boolean, symbol, bigint
NEVER use uppercase: String, Number, Boolean, Symbol, BigInt

覚えておきましょう:

  • ラッパーはオブジェクトですが、プリミティブはオブジェクトではありません
  • TypeScript は、ラッパー型が期待される場所でプリミティブ型を問題なく受け入れます
  • TypeScript は、プリミティブ型が期待される場所でラッパー型を受け入れません
  • オートボクシングにより、プリミティブ型でもメソッドを使用できます

見分け方:ラッパーの罠

// These look similar but behave differently
const primitive: string = "hello";
const wrapper: String = new String("hello");

// Equality fails
primitive === wrapper;  // false (different types)
wrapper === wrapper;    // Wait, this is also comparing to itself...

const s1 = new String("hello");
const s2 = new String("hello");
s1 === s2;  // false! Each wrapper is a unique object

プリミティブ型のメソッドの仕組み

プリミティブ型にはメソッドがありませんが、次のコードは動作します。

'primitive'.charAt(3);  // 'm' - how?

JavaScript はオートボクシングを行います。

  1. 一時的な String ラッパーを作成する
  2. ラッパーでメソッドを呼び出す
  3. ラッパーを破棄する
  4. 結果を返す

ラッパーの欠点を伴わずに、便利にメソッドを使えます。

型の代入に関する問題

// Primitive assignable to wrapper (OK but don't do this)
const s: String = "primitive";  // Works

// Wrapper NOT assignable to primitive (Error)
function takesString(s: string) { }
takesString(new String("hello"));
//          ~~~~~~~~~~~~~~~~~~~
// Argument of type 'String' is not assignable to parameter of type 'string'.
// 'string' is a primitive, but 'String' is a wrapper object.

すべてのプリミティブ型

プリミティブ型(使用する)ラッパー型(避ける)
stringString
numberNumber
booleanBoolean
symbolSymbol
bigintBigInt

注:null と undefined にはラッパー型がありません。

ラッパー型が問題になる理由

同一性の問題
const s1 = new String("hello");
const s2 = new String("hello");

s1 == s2;   // false
s1 === s2;  // false
// Each is a distinct object
typeof の混乱
typeof "hello";              // "string"
typeof new String("hello");  // "object"
真偽値判定の落とし穴
const falsy = new Boolean(false);
if (falsy) {
  console.log("This runs!"); // Wrapper objects are always truthy
}

例外:実行時メソッド

ラッパー型の静的メソッドは使用できます。

// These are fine - not creating wrapper objects
String.fromCharCode(65);  // "A"
Number.isNaN(x);
BigInt(123);              // Creates primitive, not wrapper

ただし、型として使用したり、インスタンスを作成したりしてはいけません。

圧力に負けないための指針

1. 「String のメソッドを使う必要がある」

圧力:「String のメソッドを使いたいので、String 型にします」

回答: プリミティブ型の string でも、オートボクシングによって同じメソッドをすべて使えます。

対応: string 型を使用してください。メソッドはそのまま動作します。

2. 「TypeScript が String(大文字)と推論した」

圧力:「TypeScript が String と推論したのだから、それが正しいはずです」

回答: コードを確認してください。誤ってラッパーを作成している可能性があります。

対応: 原因を特定して修正してください。小文字を使用します。

危険信号 — 作業を止めて再検討してください

  • 型注釈に大文字の String、Number、Boolean がある
  • new String()、new Number()、new Boolean() がある
  • ラッパー型とプリミティブ型の代入に関するエラーがある
  • プリミティブ型を想定しているのに typeof x === "object" を使用している

よくある正当化(すべて誤り)

言い訳実際のところ
「String のほうがメソッドが多い」いいえ、どちらも同じメソッドを持ちます
「オブジェクトが必要だ」必要になることはほとんどありません。プリミティブのほうがシンプルです
「同じものだ」いいえ、ラッパーには同一性や真偽値判定の問題があります

クイックリファレンス

// ALWAYS use these
const s: string = "hello";
const n: number = 42;
const b: boolean = true;
const sym: symbol = Symbol();
const big: bigint = 9007199254740991n;

// NEVER use these
const s: String = "hello";   // Wrong
const n: Number = 42;        // Wrong
const b: Boolean = true;     // Wrong

要点

常に小文字のプリミティブ型を使用してください。

型として String、Number、Boolean を使用する理由はありません。大文字の型は代入エラーや同一性の問題を引き起こし、小文字のプリミティブ型に勝る利点もありません。

参考資料

Dan Vanderkam 著『Effective TypeScript』の項目 10「オブジェクトラッパー型(String、Number、Boolean、Symbol、BigInt)を避ける」に基づいています。

コメント