8️⃣

[TypeScript UtilityTypes] Exclude

2024/01/08に公開

TypeScript入門メモ
[Utility Types] Exclude について

Exclude<UnionType, ExcludedMembers>

公式ドキュメント
https://www.typescriptlang.org/docs/handbook/utility-types.html#excludeuniontype-excludedmembers

UnionType から ExcludedMembers に割り当て可能なすべてのユニオンメンバーを除外して構成される型

type T0 = Exclude<"a" | "b" | "c", "a">;
// type T0 = "b" | "c"

type T1 = Exclude<"a" | "b" | "c", "a" | "b">;
// type T1 = "c";

type T2 = Exclude<string | number | (() => void), Function>;
// type T2 = string | number
 
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; x: number }
  | { kind: "triangle"; x: number; y: number };

type T3 = Exclude<Shape, { kind: "circle" }>
// type T3 = {
//     kind: "square";
//     x: number;
// } | {
//     kind: "triangle";
//     x: number;
//     y: number;
// }

サンプルコード

ディレクトリ構造をモデル化し、ExcludeでDirTreeの型定義に役立てるみたいなことはできた。

type DirNames = {
  [dirName: string]: string | string[] | DirNames | DirNames[];
};

type Dir = DirNames[string];

type DirTree = Exclude<DirNames[string], string | string[]>;

// ディレクトリ構造の例
const myDirectory: DirNames = {
  "src": {
    "app": ["app.module.ts", "app.component.ts"],
    "assets": ["logo.png", "styles.css"],
    "environments": {
      "environment.prod.ts": "",
      "environment.ts": ""
    }
  },
  "README.md": "",
  "package.json": ""
};

function extractSubdirectories(dir: DirNames): DirTree[] {
  let subdirectories: DirTree[] = [];
  for (const key in dir) {
    if (dir.hasOwnProperty(key)) {
      const value = dir[key];
      if (typeof value === "object" && !Array.isArray(value)) {
        subdirectories.push(value as DirTree);
      }
    }
  }
  return subdirectories;
}

const subdirs = extractSubdirectories(myDirectory);
console.log(subdirs); // 'environments' オブジェクトが含まれる

// [LOG]: [{
//   "app": [
//     "app.module.ts",
//     "app.component.ts"
//   ],
//   "assets": [
//     "logo.png",
//     "styles.css"
//   ],
//   "environments": {
//     "environment.prod.ts": "",
//     "environment.ts": ""
//   }
// }]

playgroundにもコード残してます。
https://www.typescriptlang.org/play?ssl=53&ssc=1&pln=1&pc=1#code/C4TwDgpgBAIglgJwHIEMC2EDOUC8UDeAUFFANoAmiqGAXFJsAnAHYDmAunQ021AD71GLVqXb9YVdFnHxkUzKIDchAL7LCoSBIS5t1LKW7D26zdFkAVBBGh4AogA8AxgBsAruQgAeWfoVG2dgAaQR5WcQCRdgA+dQB6OKhAcYZAYoZAG4ZAeoZACYZAK4ZAactAAgTAOwZAaPlCJwB7ZgYoNBBZCCdgCoQQOl95XSISACJMBCceum6SKB6UMDAhsnHJgDo0CvI3Fwg54EwekNmwOcq0MCqIZmB1zeDiUfHMTAgN6dIelwrWCrmwNi2xhhBVzD2bj0LqMxscAG6IKoYE6bYaXEE9cGQ5jQ05gBBLM7THpbeFXJEYlHHU73Og4vEqS4qIKXHoAJTsAEEYABZOwLcjY3G9MAoJwAaxQrDWACtMFUuap1AAzNzMJpwKpQCAORh84AAZTcACNKNYmi04FgABR69qSDCYACU5oQVhsogIl1WwHoOr1jWaTCwtvtEEdeCUl2lLSgxsq1Vd-IgICgLCgeqtTpBcGlYb1cwAFihMAB5ADuzAAChjIAhQMboyArUmRiCIzUwSh3LYE4hSFWTHiSKmw2YKmmmy3cDg8D0KtqRZ6elAAGSzqAAQkZCAQKBAczgmBXa5AxqHbggNeTINGmHdiE9hqw7zcmEz++bh6gOe0fqtylPUEpIJ-38u1jAG4CDMG6uqXga3qYMolLlFUNTnuBCDYHgKpqk0WpIVeUHGnUDSQdWygNhUqxzM8rDGoherWooUAJFAADkBJQsSmAMVAgBVDIAawyAB0MgDlDNkgAyDIA1CqAH4MgAxDIA0QyEIQ9GkAAMrmADinBkEQ9G9BMUx0KQsmJAiWkLEsKxrPcNIaVchn7IczDEliemjBcFnXLcpJkA5CLkW8HysLiFm9D8fwApsHlQE5+mgswEKEqisJOv5kXRSxJzvBi5BYmSfkRb0zFEilbnkhZlL0SoYiEEAA

Docusaurusで使用されていたのを参考
https://github.com/facebook/docusaurus/blob/3389daefacec9b8d927442e4af54c6d93b9cc88f/packages/docusaurus/src/client/flat.ts#L11

まとめ

型を把握するのに時間がかかる。命名には気をつけたい。

Discussion