3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TypeScript③(ユーティリティタイプ)

Last updated at Posted at 2021-06-23

この記事について

この記事は私がTypeScriptについて学んだ内容を
TypeScript①(基礎)
TypeScript②(型の機能)
TypeScript③(ユーティリティタイプ)
の3回に分けて網羅的に紹介していきます。

①(基礎)では導入方法と様々な型について簡単な紹介
②(型の機能)では型が実際にどういう働きをするのかについて

今回は、型変換を容易にするユーティリティ型についてです。

参考リンク

ユーティリティタイプ

TypeScriptは、一般的な型変換を容易にするいくつかのユーティリティ型を提供します。これらのユーティリティはグローバルに利用できます。

Partial型

オブジェクトタイプのすべてのプロパティをオプションにします

interface Todo {
  title: string;
  description: string;
}
const todo1: Todo = { 
  title: "foo", // descriptionがないためエラー
};
const todo2: Partial<Todo> = {
  title: "foo", // ok
};

Required型

オブジェクトタイプのすべてのプロパティを必須になります

interface Todo {
  title?: string;
  description?: string;
}
const todo1: Todo = { 
  title: "foo", // ok
};
const todo2: Required<Todo> = {
  title: "foo", // descriptionがないためエラー
};

Readonly型

オブジェクトタイプのすべてのプロパティを読み取り専用にします

interface Todo {
  title: string;
  description: string;
}
const todo: Readonly<Todo> = {
  title: "foo",
  description: "bar",
};
todo.title = "fooo"; // 読み取り専用プロパティであるため、'title' に代入することはできません。

Record型

Record<K,T> キーにK、値にTを持つオブジェクトタイプになります

interface CatInfo {
  age: number;
  breed: string;
}
type CatName = "miffy" | "boris" | "mordred";
const cats: Record<CatName, CatInfo> = {
  miffy: { age: 10, breed: "Persian" },
  boris: { age: 5, breed: "Maine Coon" },
  mordred: { age: 16, breed: "British Shorthair" },
};

Pick型

Pick<T,K> 型Tの中のプロパティKを持つオブジェクトタイプになります

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoPreview = Pick<Todo, "title" | "completed">;

const todo: TodoPreview = {
  title: "Clean room",
  completed: false,
};

Omit型

Omit<T, K> 型Tの中のプロパティKを除いたオブジェクトタイプになります

interface Todo {
  title: string;
  description: string;
  completed: boolean;
  createdAt: number;
}
type TodoInfo = Omit<Todo, "completed" | "createdAt">;

const todoInfo: TodoInfo = {
  title: "Pick up kids",
  description: "Kindergarten closes at 5pm",
};

Exclude型

Exclud<T,K> 型Tから型Uと関連するプロパティを除いたオブジェクトタイプになります

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

Extract型

Extract<T,K> 型Tと型Kの両方に共通するプロパティだけを持つオブジェクトタイプになります

type T0 = Extract<"a" | "b" | "c", "a" | "f">; // type T0 = "a"
     
type T1 = Extract<string | number | (() => void), Function>; // type T1 = () => void

NonNullable型

nullとundefinedを除いたオブジェクトタイプになります

type T0 = NonNullable<string | number | undefined>; // type T0 = string | number

type T1 = NonNullable<string[] | null | undefined>; // type T1 = string[]

Parameters型

Parameters<T> Tに関数型を受け取り、受け取った型をタプル型として持つオブジェクトタイプになります。
declareはParameters型とは関係ないですが、アンビエント宣言といって関数の型定義を明示的に表したものです。

declare function f1(arg: { a: number; b: string }): void;

type T0 = Parameters<() => string>; // type T0 = []

type T1 = Parameters<(s: string) => void>; // type T1 = [s: string]

type T3 = Parameters<typeof f1>; // type T3 = [arg: { a: number; b: string; }]

ConstructorParameters型

ConstructorParameters<T> Tにコンストラクタの引数の型をタプル型として持つオブジェクトタイプになります。 Parametersのコンストラクタ版です。

class Foo {
  constructor(arg1: string, arg2?: boolean) {}
}

type Bar = ConstructorParameters<typeof Foo>; // [string, boolean] | [string]

ReturnType型

ReturnType<T> Tで受け取った関数型の戻り型を持つオブジェクトタイプになります

declare function f1(): { a: number; b: string };

type T0 = ReturnType<() => string>; // type T0 = string

type T1 = ReturnType<(s: string) => void>; // type T1 = void

type T4 = ReturnType<typeof f1>; // type T4 = { a: number; b: string; }

InstanceType型

InstanceType<T> Tで受け取ったコンストラクター関数のインスタンス型を持つオブジェクトタイプになります

class C {
  x = 0;
  y = 0;
}

type T = InstanceType<typeof C>; // type T = C

ThisParameterType型

Parameters型ではthisを受け取れないのに対し、ThisParameterType型では受け取った関数型のthisパラメーターの型を持つオブジェクトタイプになります

function fn(this: { a: string }, b: number): string {
  return this.a;
}
type T0 = typeof fn;

type T1 = Parameters<T0>; // type Param = [b: number]

type T2 = ThisParameterType<T0>; // type T2 = { a: string; }

OmitThisParameter型

受け取った関数型のthisパラメーターの型を除いた残りの型を持つオブジェクトタイプになります

declare function fn(this: { a: string; b: boolean }, c: number): void;
type T0 = typeof fn;

type T1 = OmitThisParameter<T0>; // type T1 = (c: number) => void

ThisType型

ThisType<T> Tのプロパティをthisで扱えるようにします

type ObjectDescriptor<D, M> = {
    data?: D;
    methods?: M & ThisType<D & M>; // methodsのthisの型がD&Mになります
  };
  
  function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M {
    let data: object = desc.data || {};
    let methods: object = desc.methods || {};
    return { ...data, ...methods } as D & M;
  }
  
let obj = makeObject({
  data: { x: 0, y: 0 },
  methods: {
    moveBy(dx: number, dy: number) {
      this.x += dx; // D(dataのプロパティ)がthisで利用できる
      this.y += dy;
    },
    double(dx, dy) {
      this.moveBy(dx, dy); // M(methodsのプロパティ)がthisで利用できる
      this.moveBy(dx, dy);
    },
  },
});

obj.double(5, 5);

Uppercase型

文字列内の各文字を大文字に変換します

type Greeting = "Hello, world"
type ShoutyGreeting = Uppercase<Greeting> // type ShoutyGreeting = "HELLO, WORLD"

type ASCIICacheKey<Str extends string> = `ID-${Uppercase<Str>}`
type MainID = ASCIICacheKey<"my_app"> // type MainID = "ID-MY_APP"

Lowercase型

文字列内の各文字を同等の小文字に変換します

type Greeting = "Hello, world"
type QuietGreeting = Lowercase<Greeting> // type QuietGreeting = "hello, world"

type ASCIICacheKey<Str extends string> = `id-${Lowercase<Str>}`
type MainID = ASCIICacheKey<"MY_APP"> // type MainID = "id-my_app"

Capitalize型

文字列の最初の文字を大文字に変換します

type LowercaseGreeting = "hello, world";
type Greeting = Capitalize<LowercaseGreeting>; // type Greeting = "Hello, world"

Uncapitalize型

文字列の最初の文字を小文字に変換します

type UppercaseGreeting = "HELLO WORLD";
type UncomfortableGreeting = Uncapitalize<UppercaseGreeting>; // type UncomfortableGreeting = "hELLO WORLD"

おわりに

今回勉強してきた以外にもTypeScriptにはたくさんの機能や特徴があります。TypeSctipt以外にも学ばないといけないことはたくさんあり、日々更新される変更や追加機能に私自身全くついていけていないですが、焦らず、学びに楽しみを見出しながら続けていきたいと思います。
最後まで読んでいただきありがとうございました。


関連記事

TypeScript①(基礎)
TypeScript②(型の機能)

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?