1
0

TypeScriptの中級コース~TypeScriptにどっぷり浸かろう!~

Last updated at Posted at 2024-08-03

TypeScriptを極めよう!

TypeScriptは次世代のVBAになるほどMicrosoftがプッシュしています。
TypeScriptからファイルシステムにアクセスすることはできませんが
PowerAutomateと一緒に使うことで高度な処理が実現できます。

それではいきましょう!

1. 型推論の高度な使用法

TypeScriptの型推論は非常に強力です。複雑な型推論の例を見てみましょう。

function createPair<T, U>(v1: T, v2: U): [T, U] {
  return [v1, v2];
}

let pair = createPair("hello", 42);
// pairの型は [string, number] と推論されます

2. 条件付き型の応用

条件付き型を使用して、入力に基づいて型を動的に選択できます。

type TypeName<T> = 
    T extends string ? "string" :
    T extends number ? "number" :
    T extends boolean ? "boolean" :
    T extends undefined ? "undefined" :
    T extends Function ? "function" :
    "object";

type T0 = TypeName<string>;  // "string"
type T1 = TypeName<"a">;     // "string"
type T2 = TypeName<true>;    // "boolean"
type T3 = TypeName<() => void>;  // "function"
type T4 = TypeName<string[]>;    // "object"

3. マップ型と高度な型変換

マップ型を使用して、既存の型から新しい型を作成できます。

type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

type Partial<T> = {
    [P in keyof T]?: T[P];
};

interface Person {
    name: string;
    age: number;
}

type ReadonlyPerson = Readonly<Person>;
// { readonly name: string; readonly age: number; }

type PartialPerson = Partial<Person>;
// { name?: string; age?: number; }

4. 高度なジェネリック制約

ジェネリック型に複雑な制約を適用できます。

interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);  // プロパティ 'length' は存在します
    return arg;
}

loggingIdentity(3);  // エラー、numberには 'length' プロパティがありません
loggingIdentity({length: 10, value: 3});  // OK

5. 型の交差と合成

型の交差を使用して、複数の型を組み合わせることができます。

interface ErrorHandling {
    success: boolean;
    error?: { message: string };
}

interface ArtworksData {
    artworks: { title: string }[];
}

type ArtworksResponse = ArtworksData & ErrorHandling;

let response: ArtworksResponse = {
    artworks: [{ title: "Mona Lisa" }],
    success: true
};

6. 高度なインデックス型

インデックス型を使用して、オブジェクトのプロパティを動的に参照できます。

function pluck<T, K extends keyof T>(o: T, propertyNames: K[]): T[K][] {
  return propertyNames.map(n => o[n]);
}

interface Car {
    manufacturer: string;
    model: string;
    year: number;
}

let taxi: Car = {
    manufacturer: 'Toyota',
    model: 'Camry',
    year: 2014
};

let makeAndModel = pluck(taxi, ['manufacturer', 'model']);
// makeAndModelの型は (string | number)[]

7. 型ガードとアサーション関数

カスタム型ガードを作成して、より精密な型チェックを行うことができます。

interface Bird {
    fly(): void;
    layEggs(): void;
}

interface Fish {
    swim(): void;
    layEggs(): void;
}

function isFish(pet: Fish | Bird): pet is Fish {
    return (pet as Fish).swim !== undefined;
}

function move(pet: Fish | Bird) {
    if (isFish(pet)) {
        pet.swim();
    } else {
        pet.fly();
    }
}

8. 再帰型

再帰型を使用して、ネストされたデータ構造を表現できます。

type JSONValue = 
    | string
    | number
    | boolean
    | null
    | JSONValue[]
    | { [key: string]: JSONValue };

const data: JSONValue = {
    name: "John",
    age: 30,
    isStudent: false,
    hobbies: ["reading", "swimming"],
    address: {
        street: "123 Main St",
        city: "Anytown"
    }
};

9. テンプレートリテラル型の高度な使用法

テンプレートリテラル型を使用して、文字列ベースの複雑な型を作成できます。

type EmailLocaleIDs = "welcome_email" | "email_heading";
type FooterLocaleIDs = "footer_title" | "footer_sendoff";

type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`;
// "welcome_email_id" | "email_heading_id" | "footer_title_id" | "footer_sendoff_id"

type Lang = "en" | "ja" | "pt";

type LocaleMessageIDs = `${Lang}_${AllLocaleIDs}`;
// "en_welcome_email_id" | "en_email_heading_id" | "en_footer_title_id" | "en_footer_sendoff_id" |
// "ja_welcome_email_id" | "ja_email_heading_id" | "ja_footer_title_id" | "ja_footer_sendoff_id" |
// "pt_welcome_email_id" | "pt_email_heading_id" | "pt_footer_title_id" | "pt_footer_sendoff_id"

10. 高度な型レベルプログラミング

TypeScriptの型システムを使用して、複雑な計算を型レベルで実行できます。

type Subtract<T extends number, U extends number> = 
    [...Array<T>]['length'] extends [...Array<U>, ...infer Rest] 
    ? Rest['length'] 
    : never;

type Result = Subtract<5, 3>; // 2

type Fibonacci<N extends number, A extends number[] = [1], B extends number[] = [1]> = 
    N extends 0 ? 0 :
    N extends 1 ? 1 :
    N extends 2 ? 1 :
    A['length'] extends N ? B['length'] :
    Fibonacci<N, B, [...A, ...B]>;

type Fib5 = Fibonacci<5>; // 5
type Fib10 = Fibonacci<10>; // 55

これらの高度な型システムの機能を理解し活用することで、より堅牢で表現力豊かなTypeScriptコードを書くことができます。型システムを深く理解することは、バグの早期発見やコードの自己文書化につながり、大規模なアプリケーション開発において非常に有益です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0