もう迷わない!TypeScript除外型の使い道とサンプルコード集
TypeScriptにおける除外型を使用した「すべての文字列値」型
具体的な例
以下は、'exclude-string'
という文字列を除いたすべての文字列値を表す型を定義する例です。
type ExceptString = Exclude<string, 'exclude-string'>;
この型を使用すると、以下のようになります。
let value: ExceptString = 'hello'; // 型エラーなし
let value2: ExceptString = 'exclude-string'; // 型エラー
value
変数には、'exclude-string'
以外の任意の文字列を代入できます。一方、value2
変数には 'exclude-string'
を代入することはできません。
除外型のバリエーション
除外型は、より複雑な条件を定義するために、複数の型を組み合わせることもできます。例えば、以下の型は、'exclude-string1'
と 'exclude-string2'
を除いたすべての文字列値を表します。
type ExceptStrings = Exclude<string, 'exclude-string1' | 'exclude-string2'>;
さらに、never
型を使用して、特定の条件に一致するすべての値を除外することもできます。例えば、以下の型は、空文字列または長さ0の文字列を除いたすべての文字列値を表します。
type NonEmptyString = Exclude<string, '' | never>;
使用例
除外型は、以下のようなさまざまな場面で使用できます。
- 特定の文字列を含むオブジェクトをフィルタリングする
- フォーム入力から特定の値を除外する
- APIレスポンスから特定のエラーメッセージを除外する
- 除外型を使用する場合は、定義が明確でわかりやすいようにすることが重要です。複雑な除外型は、コードの読みやすさを損なう可能性があります。
- 除外型は、コンパイラによる型チェックを強化するのに役立ちますが、実行時の型チェックは保証しません。
type ApiResponse = {
code: number;
message: string;
};
type ValidApiResponse = Exclude<ApiResponse, { code: 404 | 500 }>;
const response: ValidApiResponse = {
code: 200,
message: 'Success'
};
console.log(response.code); // 200
console.log(response.message); // Success
このコードでは、ApiResponse
型はAPIレスポンスの構造を定義します。code
プロパティはエラーコードを表し、message
プロパティはエラーメッセージを表します。
ValidApiResponse
型は、ApiResponse
型からcode
プロパティが404または500であるオブジェクトを除外した型です。つまり、この型は、code
プロパティが200以外のオブジェクトを表します。
response
変数には、ValidApiResponse
型のオブジェクトが代入されます。これは、code
プロパティが200で、message
プロパティが'Success'
であることを意味します。
この例では、フォーム入力から空文字列と'select-option'
の値を除外する型を定義します。
type FormInput = string;
type ValidFormInput = Exclude<FormInput, '' | 'select-option'>;
const inputValue: ValidFormInput = 'user-input';
console.log(inputValue); // user-input
このコードでは、FormInput
型はフォーム入力の値を表します。
ValidFormInput
型は、FormInput
型から空文字列と'select-option'
の値を除外した型です。つまり、この型は、空文字列または'select-option'
以外の文字列を表します。
inputValue
変数には、ValidFormInput
型の値が代入されます。これは、入力値が空文字列または'select-option'
ではないことを意味します。
この例では、'name'
プロパティに特定の文字列が含まれないオブジェクトをフィルタリングする関数を定義します。
type User = {
id: number;
name: string;
};
const users: User[] = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
];
const filteredUsers = users.filter((user: User) => !excludedNames.includes(user.name));
console.log(filteredUsers); // [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
このコードでは、User
型はユーザーを表します。id
プロパティはユーザーIDを表し、name
プロパティはユーザー名を表します。
users
変数は、User
型のオブジェクトの配列です。
filteredUsers
変数は、users
配列から'Charlie'
という名前を持つユーザーを除外した新しい配列です。
filter
メソッドは、配列内の各要素に対してコールバック関数を呼び出し、その結果に基づいて新しい配列を作成します。
never型とジェネリック型を使用した方法
この方法は、除外したい文字列の数が少ない場合に有効です。
type ExceptStrings<T extends string, S extends string> = never extends Exclude<T, S> ? never : T;
上記のジェネリック型ExceptStrings
を使用すると、以下のようになります。
type ExceptString = ExceptStrings<string, 'exclude-string'>;
これはExclude<string, 'exclude-string'>
と同じですが、ジェネリック型を使用することで、より柔軟で再利用可能なコードになります。
Pick型とOmit型を使用した方法
この方法は、除外したいプロパティと保持したいプロパティを明確に指定したい場合に有効です。
type User = {
id: number;
name: string;
email: string;
};
type WithoutEmail = Omit<User, 'email'>; // { id: number; name: string; }
上記の例では、Omit
型を使用して、User
型からemail
プロパティを除外した新しい型WithoutEmail
を定義しています。
同様に、Pick
型を使用して、特定のプロパティのみを含む新しい型を定義することもできます。
type WithIdAndName = Pick<User, 'id' | 'name'>; // { id: number; name: string; }
カスタム型ガードを使用した方法
この方法は、より複雑な条件に基づいて文字列を除外したい場合に有効です。
function isExcludedString(value: string): value is 'exclude-string1' | 'exclude-string2' {
return value === 'exclude-string1' || value === 'exclude-string2';
}
type ExceptStrings = Exclude<string, typeof isExcludedString>;
上記の例では、isExcludedString
というカスタム型ガード関数を作成しています。この関数は、引数の文字列が'exclude-string1'
または'exclude-string2'
であるかどうかを判定します。
ExceptStrings
型は、isExcludedString
型ガード関数によってtrue
を返すすべての文字列を除外した型です。
適切な方法の選択
どの方法が適切かは、具体的な状況によって異なります。
- より複雑な条件に基づいて文字列を除外したい場合は、カスタム型ガードを使用した方法が柔軟性と制御を提供します。
- 除外したいプロパティと保持したいプロパティを明確に指定したい場合は、
Pick
型とOmit
型を使用した方法が適切です。 - 除外したい文字列の数が少ない場合は、
never
型とジェネリック型を使用した方法が簡潔で効率的です。
typescript