[TypeScript] 関数内で扱う型を引数のように受け取るジェネリクス関数

typescript-generics
INDEX

はじめに

初めてのTypeScriptを読みました。
その学習を記録します。

40036_learning_typescript_cvr

結論

ジェネリクス関数とは、データ型を引数のように扱う関数のこと
型引数(type argument)=データ型を引数のように扱う

const 関数名 = <関数内で扱うデータ型>(引数名: 関数内で扱うデータ型[]) => 処理;

使い方

それぞれのデータ型で関数を作成する

似たような関数が量産されてしまう

// 数値型の配列の末尾のデータを取得する関数
const getEndElementOfNum = (list: number[]) => list.at(-1);
// 文字列型の配列の末尾のデータを取得する関数
const getEndElementOfStr = (list: string[]) => list.at(-1);

console.log(getEndElementOfNum([1, 2, 3, 4]));
console.log(getEndElementOfStr(['a', 'b', 'c']));
実行結果を確認する
4
c

any型で共有化

似たような関数を量産せず済む

any型の為、意図しないデータ型を処理してしまう

// 配列の末尾のデータを取得する関数
const getEndElementOfAny = (list: any[]) => list.at(-1);

console.log(getEndElementOfAny([1, 2, 3, 4]));
console.log(getEndElementOfAny(['a', 'b', 'c']));
実行結果を確認する
4
c

ジェネリック関数

似たような関数を量産せず済む
関数内部を確認しなくても、関数外部からデータ型を確認できる

const getEndElement = <T>(list: T[]) => list.at(-1);

console.log(getEndElement<number>([1, 2, 3, 4]));
console.log(getEndElement<string>(['a', 'b', 'c']));
実行結果を確認する
4
c

複数の型引数の活用

2つのデータ型を

const getEndElement1 = <T, U>(arg1: T, arg2: U) => {
  console.log(arg1, typeof arg1);
  console.log(arg2, typeof arg2);
}

getEndElement1(1, 'a')
実行結果を確認する
1 number
a string

コンポーネント(JSX構文、.tsxファイル)でのジェネリクなアロー関数

ジェネリック関数をそのままコンポーネント(JSX構文、.tsxファイル)を使用すると下記のようなエラーが発生します。

const identity = <T>(arg: T): T => arg;
JSX 要素 'T' には対応する終了タグがありません
JSX element 'T' has no corresponding closing tag.

<関数内で扱うデータ型><関数内で扱うデータ型 = unknown >に変更して制約を追加する

T = unknownは、ジェネリック型 T のデフォルトの型を指定しています。unknownはTypeScript 2.0以降で導入された型で、他の型に関する情報がないことを表します。つまり、Tがどの型であるかはわからず、そのままの状態で受け入れられます。これにより、関数が受け取る引数の型と同じ型を返すという振る舞いが実現されます。

const identity = <T = unknown>(arg: T): T => arg;
よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

Born in 1994
Engineer's career is from 2020.10
Skill: Next.js, TypeScript, Django, Python, HTML, CSS

INDEX