404 Not Found

404 Not Found


nginx

TypeScript の関数型

関数はJavaScriptの中核をなす構成要素であり、TypeScriptでは関数の引数や戻り値に包括的な型システムが追加されており、関数の「入力」と「出力」が明確に定義されるようになっています。

1. 関数型のアノテーション

(1) パラメータおよび戻り値の型

TYPESCRIPT
function add(a: number, b: number): number {
  return a + b;
}

let result = add(1, 2);    // result Inferred as number
// add("1", "2");          // ❌ Parameter types do not match
// add(1);                 // ❌ Insufficient number of parameters

(2) 戻り値型の推論

TypeScript は return 文に基づいて戻り値の型を推論できますが、明示的に指定することをお勧めします:

TYPESCRIPT
// Return Type Inference——Can be inferred, but not recommended(It's easy to make mistakes when deriving large functions)
function multiply(a: number, b: number) {
  return a * b;   // Inference Return number
}

// Explicit Annotation——Recommendations(Purpose of the Document + Compile-time errors)
function divide(a: number, b: number): number {
  if (b === 0) throw new Error("The divisor cannot be zero.");
  return a / b;
}

(3) void 戻り値の型

関数の戻り値がない場合は、void を使用してください:

TYPESCRIPT
function log(message: string): void {
  console.log(message);
  // None return Statement,Or return; —— All of them void
}

(4) 値を返さない

関数が決して値を返さず、例外をスローするか、無限ループに入る場合は、never を使用してください:

TYPESCRIPT
function throwError(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) { }
}
戻り値の型 意味
void 関数は正常に実行されたが、値を返さなかった
never 関数が終了しない(例外が発生するか、無限ループに陥る)

▶ 例:型付きユーティリティ関数

TYPESCRIPT
function clamp(value: number, min: number, max: number): number {
  return Math.min(Math.max(value, min), max);
}

function formatCurrency(amount: number, symbol: string = "¥"): string {
  return symbol + amount.toFixed(2);
}

console.log(clamp(150, 0, 100));           // 100
console.log(clamp(-5, 0, 100));            // 0
console.log(clamp(50, 0, 100));            // 50
console.log(formatCurrency(99.5));         // ¥99.50
console.log(formatCurrency(42, "$"));      // $42.00

出力:

TEXT
100
0
50
¥99.50
$42.00

2. オプションのパラメータとデフォルトのパラメータ

(1) オプションパラメータ ?

TYPESCRIPT
function greet(name: string, title?: string): string {
  if (title) {
    return `${title} ${name}`;
  }
  return `Hello,${name}`;
}

console.log(greet("Charlie"));           // "Hello,Charlie"
console.log(greet("Charlie", "Engineer"));  // "Engineer Charlie"
⚠️ ルール:オプションのパラメータは、必須のパラメータの後に指定する必要があります。function greet(title?: string, name: string) とするとエラーになります。

(2) デフォルトのパラメータ

TYPESCRIPT
function createUser(name: string, role: string = "viewer", active: boolean = true): string {
  return `${name},Characters:${role},${active ? "Active" : "Not activated"}`;
}

console.log(createUser("Charlie"));                       // Charlie,Characters:viewer,Active
console.log(createUser("Diana", "editor"));             // Diana,Characters:editor,Active
console.log(createUser("Eric", "admin", false));       // Eric,Characters:admin,Not activated

(3) オプションのパラメータとデフォルトのパラメータ

機能 オプションパラメータ title?: string デフォルトパラメータ role: string = "viewer"
呼び出されたとき 省略可能。値は未定義 省略可能。値はデフォルト値
タイプ string | undefined string(未定義の共用体ではない)
推奨事項 その値は確かに未定義である可能性がある ほとんどの場合、妥当なデフォルト値を設定しておくほうがよい

3. その他のパラメータ

... という構文を使用して、残りのパラメータを配列にまとめます:

TYPESCRIPT
function sum(first: number, ...rest: number[]): number {
  return rest.reduce((total, n) => total + n, first);
}

console.log(sum(1));             // 1
console.log(sum(1, 2));         // 3
console.log(sum(1, 2, 3, 4));   // 10

(1) 残りのパラメータは配列型でなければならない

TYPESCRIPT
function logAll(prefix: string, ...messages: string[]): void {
  messages.forEach(msg => console.log(`${prefix}: ${msg}`));
}

logAll("DEBUG", "Start the service", "Connect to the Database", "Ready");

出力:

TEXT
DEBUG: Start the service
DEBUG: Connect to the Database
DEBUG: Ready

4. 関数型式

関数は値渡しすることも可能です。その場合、型を指定するために関数型式が使用されます:

(1) 型エイリアスは関数型を定義する

TYPESCRIPT
type MathOperation = (a: number, b: number) => number;

let add: MathOperation = (a, b) => a + b;
let subtract: MathOperation = (a, b) => a - b;
let multiply: MathOperation = (a, b) => a * b;

console.log(add(10, 5));       // 15
console.log(subtract(10, 5));  // 5
console.log(multiply(10, 5));  // 50

(2) コールバック関数の型

関数型の最も一般的な用途は、コールバック関数のシグネチャを記述することです:

TYPESCRIPT
function fetchData(url: string, onSuccess: (data: string) => void, onError: (error: Error) => void): void {
  // Simulating Asynchronous Operations
  if (url.startsWith("https://")) {
    onSuccess("Data loaded successfully");
  } else {
    onError(new Error("Supports only HTTPS"));
  }
}

fetchData(
  "https://api.example.com",
  data => console.log(data),         // ✅ (data: string) => void
  error => console.log(error.message) // ✅ (error: Error) => void
);

(3) インターフェースを用いた関数型の定義

TYPESCRIPT
interface Comparator {
  (a: number, b: number): number;
}

let ascending: Comparator = (a, b) => a - b;
let descending: Comparator = (a, b) => b - a;

let nums = [3, 1, 4, 1, 5];
console.log([...nums].sort(ascending));   // [1, 1, 3, 4, 5]
console.log([...nums].sort(descending));  // [5, 4, 3, 1, 1]

5. 関数のオーバーロード

関数のオーバーロードにより、1つの関数名で引数の型のさまざまな組み合わせに対応できるようになります。TypeScriptのオーバーロードは、「宣言+実装」というパターンに従います:

(1) 基本的な構文

TYPESCRIPT
// Overloaded Signatures——Describe the return type for each parameter combination
function format(value: number): string;
function format(value: string): string;
function format(value: Date): string;

// Implementing Signatures——Must be compatible with all overloaded signatures
function format(value: number | string | Date): string {
  if (typeof value === "number") {
    return value.toFixed(2);
  } else if (typeof value === "string") {
    return value.trim();
  } else {
    return value.toISOString();
  }
}

console.log(format(3.14));             // "3.14"
console.log(format("  hello  "));      // "hello"
console.log(format(new Date()));       // "2024-..."

(2) オーバーロードの順序

TypeScript は、オーバーロードされたメソッドを宣言された順序(上から下へ)で照合するため、より具体的なオーバーロードを先に記述する必要があります:

TYPESCRIPT
// ✅ Correct Order——The specifics come first
function process(value: string): string;
function process(value: any): unknown;

// ❌ Incorrect Order——any Matches all parameters,The overloaded version that comes later will never be called.
// function process(value: any): unknown;
// function process(value: string): string;

▶ 例:型安全なイベント処理を実装するためのオーバーロード

TYPESCRIPT
function on(event: "click", handler: (x: number, y: number) => void): void;
function on(event: "keydown", handler: (key: string) => void): void;
function on(event: string, handler: Function): void {
  console.log(`Registration Event:${event}`);
  // Implementation details omitted...
}

// Automatically determines the correct parameter types upon invocation
on("click", (x, y) => {
  console.log(`Click here:(${x}, ${y})`);   // x, y Inferred as number
});

on("keydown", (key) => {
  console.log(`Press the button:${key}`);           // key Inferred as string
});

6. 矢印関数の種類

(1) 矢印関数の型注釈

TYPESCRIPT
const add = (a: number, b: number): number => a + b;

// When acting as a callback,Parameter types can usually be inferred
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2);       // n Inferred as number
const asStrings = nums.map(n => String(n)); // n Inferred as number

(2) 矢印関数と this

矢印関数は独自の this をバインドせず、外側の this を継承します:

TYPESCRIPT
class Timer {
  seconds = 0;

  start() {
    // Arrow Functions——this Orientation Timer Examples
    setInterval(() => {
      this.seconds++;
      console.log(`${this.seconds}s`);
    }, 1000);
  }

  startBroken() {
    // Ordinary Functions——this Points to the global or undefined(Strict Mode)
    setInterval(function () {
      // this.seconds++;  // ❌ Runtime this No Timer
    }, 1000);
  }
}

❓ よくある質問

Q 関数の戻り値の型は明示的に指定すべきですか?
A 指定することをお勧めします。TypeScriptでは型推論が可能ですが、明示的に指定することには3つの利点があります:(1) ドキュメント化――戻り値の型が一目でわかります;(2) 誤って間違った型の値を返すのを防げます;(3) エラーの特定が容易になります――エラーは呼び出し箇所ではなく、関数のシグネチャで報告されます。短い関数(1行の関数 return)では戻り値の型を省略しても構いませんが、3行を超える関数では明示的に指定することを推奨します。
Q 戻り値の型 voidundefined の違いは何ですか?
A void は「関数は戻り値を気にしない」という意味です。つまり、関数に return 文がある場合もあればない場合もあり、呼び出し側は戻り値を使用すべきではありません。undefinedは特定の型であり、関数は明示的にundefinedを返します。実際の開発では、戻り値のない関数はすべてvoidを使用します。
Q 関数のオーバーロードとユニオン型パラメータの違いは何ですか?
A ユニオン型 function fn(x: string | number) は、「パラメータがこれらの型のいずれかである」ことを記述することしかできませんが、すべてのパラメータの組み合わせが同じ型を返します。オーバーロードでは、「異なるパラメータの組み合わせによって異なる型を返す」ことが可能ですが、これはユニオン型では実現できません。パラメータの型に柔軟性があり、戻り値の型が統一されている場合は、ユニオン型を使用する方が簡潔です。異なる戻り値の型が必要な場合は、オーバーロードを使用してください。
Q デフォルトパラメータとオプションパラメータを併用することはできますか?
A いいえ。function fn(x?: string = "hi") は構文エラーです。デフォルトパラメータはすでに「オプション」であることが暗黙的に想定されているため、? を追加する必要はありません。x: string = "hi"x?: string と同等ですが、その値は未定義ではなく「hi」となります。

📖 まとめ

📝 練習問題

  1. 基本演習(難易度 ⭐):パラメータと戻り値の両方が型 number である 3 つの関数、すなわち加算用の add(a, b)、減算用の subtract(a, b)、乗算用の multiply(a, b) を実装してください。関数型式を使用して、型を統一的に宣言してください。
  2. 上級問題(難易度 ⭐⭐):オブジェクトをURLのクエリ文字列に変換する関数 buildQuery(params: Record<string, string | number | boolean>) を作成してください。例えば、{ page: 1, size: 10, active: true }"page=1&size=10&active=true" のように変換します。
  3. 課題(難易度 ⭐⭐⭐):関数のオーバーロードを使用してこれを実装してください createElement(tag, props):タグが「input」の場合は props は type: string でなければなりません;タグが「a」の場合は props は href: string でなければなりません;タグが「div」の場合は props はジェネリックオブジェクトとなります。各ケースごとに異なるタイプの説明オブジェクトを返すこと。
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%