TypeScriptで「undefined」と「void」を使い分ける方法:サンプルコード付き
TypeScriptにおける「undefined」と「void」の使い分け:徹底解説
undefinedとは何か?
undefined
は、変数に値が代入されていないことを表すプリミティブ型です。変数宣言時に初期化されていない場合や、明示的にundefined
を代入した場合に発生します。
let x; // x は undefined になる
let y: number;
y = undefined; // y も undefined になる
また、関数から値を返さない場合も、暗黙的にundefined
が返されます。
function noReturn() {
// 何も返さない
}
let result = noReturn(); // result は undefined になる
voidとは何か?
void
は、関数の戻り値の型を表すために使用する特殊な型です。「戻り値が存在しない」または「処理完了のみを示す」ことを意味します。
function logMessage(message: string): void {
console.log(message);
}
// 戻り値は使わないため、void型を指定
let result = logMessage("Hello!");
void
は、単に「値が存在しない」という意味のundefined
とは異なります。void
はあくまでも関数の戻り値に特化した型であり、変数に代入することはできません。
undefinedとvoidの使い分け
- 変数の型注釈
- 値が代入されていない可能性がある変数には、
undefined
型の注釈を使用します。 - 確実に値が存在しない変数には、
null
型の注釈を使用します。
- 値が代入されていない可能性がある変数には、
let message: string | undefined; // message は string または undefined になる可能性がある
let result: null; // result は常に null になる
- 関数の戻り値の型注釈
- 具体的な値を返す関数には、その値の型に一致する型注釈を使用します。
function sendMessage(message: string): void {
// 送信処理のみを行い、値を返さない
}
function getLength(str: string): number {
return str.length; // number型の値を返す
}
- 変数の型注釈には
undefined
またはnull
を使用し、関数の戻り値の型注釈にはvoid
を使用します。 void
は、関数の戻り値が存在しないことを表す特殊な型です。undefined
は、変数に値が存在しないことを表すプリミティブ型です。
これらの違いを正しく理解し、使い分けることで、より明確で堅牢なTypeScriptコードを書くことができます。
- 型ガード: 特定の条件下で変数の型を絞り込むための構文です。
never
型: 関数が決して終了しないことを表す型です。
これらの概念についても理解を深めると、より高度なTypeScriptプログラミングが可能になります。
変数の型注釈
// 値が代入されていない可能性がある変数
let message: string | undefined;
// 確実に値が存在しない変数
let result: null;
この例では、message
変数はstring
型またはundefined
型になる可能性があることを示しています。一方、result
変数は常にnull
型であることを示しています。
関数の戻り値の型注釈
// 戻り値が存在しない関数
function logMessage(message: string): void {
console.log(message);
}
// 具体的な値を返す関数
function getLength(str: string): number {
return str.length;
}
この例では、logMessage
関数は戻り値を持たないため、void
型の注釈を使用しています。一方、getLength
関数はnumber
型の値を返すため、number
型の注釈を使用しています。
型ガード
function isDefined(value: string | undefined): value is string {
return typeof value === 'string';
}
let someValue: string | undefined;
if (isDefined(someValue)) {
someValue.toUpperCase(); // someValueはstring型として扱われる
} else {
// someValueはundefined型として扱われる
}
この例では、isDefined
関数は引数がstring
型かどうかを判定する型ガード関数です。この型ガードを用いることで、someValue
変数の型を条件分岐によって絞り込むことができます。
- レストパラメータ: 可変個数の引数を配列として受け取る機能です。
- デフォルトパラメータ: 関数の引数にデフォルト値を設定する機能です。
- オプションパラメータ: 関数の引数が省略可能であることを示す機能です。
型エイリアス
型エイリアスを用いることで、undefined
やvoid
を含む複雑な型をより分かりやすく定義することができます。
type MaybeString = string | undefined; // string型またはundefined型のエイリアス
type VoidFunction = (...args: any[]) => void; // 引数なしでvoidを返す関数の型エイリアス
この例では、MaybeString
型はstring
型またはundefined
型であることを意味し、VoidFunction
型は引数なしでvoid
を返す関数を表します。
ジェネリック型
ジェネリック型を用いることで、undefined
やvoid
を含む型を汎用的に定義することができます。
function identity<T>(value: T): T | undefined {
if (value === undefined) {
return undefined;
} else {
return value;
}
}
let result = identity<string>("Hello"); // resultはstring型になる
let undefinedResult = identity<number>(undefined); // undefinedResultはundefined型になる
この例では、identity
関数は引数の型に一致する型の値を返しますが、引数がundefined
の場合はundefined
を返します。ジェネリック型を用いることで、この汎用的な挙動を様々な型に適用することができます。
型推論
TypeScriptの型推論機能を活用することで、undefined
やvoid
を含む型の宣言を省略することができます。
let message = "Hello"; // messageはstring型として推論される
let result = logMessage(message); // resultはvoid型として推論される
function logMessage(message: string): void {
console.log(message);
}
この例では、message
変数はstring
型に、result
変数はvoid
型に自動的に推論されます。型注釈を明示的に記述する必要がなく、コードがより簡潔になります。
- アップキャスト: 型をより一般的な型に広げる操作です。
- 型アサーション: 特定の型であることを明示的に断言する構文です。
typescript undefined void