6
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でよく使う関数などをまとめてみた

Posted at

extends keyof

オブジェクト(配列)のkey達を取得する

export interface FormValues {
  last_name: string | null;
  first_name: string | null;
  gender: number | null;
  birthday: string | null;
}
const event = <K extends keyof FormValues>(
val: FormValues[K] // FormValuesの中のいずれかのプロパティ,
key: K, // last_name | first_name | gender | birthday
) => {
FormValues[key] = val; // オブジェクトの中の1つのプロパティに代入する
}

継承

interfaceやtypeを追加で定義する

interface Object {
  name: string;
  height: number;
}

interface newObject extends Object {
  birthday: string;
}

const data:newObject  = 
{
  name: '澁谷かのん',
  height: 159,
  birthday: '05/01',
}

合併型(Union Types)と交差型(Intersection Types)

合併型はorを表す型で、交差型は&を表す型

type Kick = {
  effect: boolean,
  hit: boolean,
};

type Punch = {
  hit: boolean,
  damage: number,
};

type KickOrPunch = Kick | Punch;
type KickAndPunch = Kick & Punch;

// 合併型なので、Kick, Punch型両方のプロパティが使える
const SuperAtack: KickOrPunch = {
  effect: true,
  hit: true,
  damage: 10,
};

// 合併型なため、どちらかの型ということを表せれば良い
const normalAtack: KickOrPunch = {
  hit: false,
  damage: 3,
};

// 合併型とはいえどちらかの型を満たせなけれNG
const errorAtack: KickOrPunch = {
  effect: false,
  damage: 3,
};
// Type '{ effect: false; damage: number; }' is not assignable to type 'KickOrPunch'.
//   Property 'hit' is missing in type '{ effect: false; damage: number; }' but required in type 'Punch'.

// 交差型なので、合併型同様Kick, Punch型両方のプロパティが使える
const doubleAtack: KickAndPunch = {
  effect: true,
  hit: true,
  damage: 10,
};

// 交差型は集合元の型全てのプロパティを使わなくてはならない
const errorAtack2: KickAndPunch = {
  hit: true,
  damage: 3,
};
// Type '{ hit: true; damage: number; }' is not assignable to type 'KickAndPunch'.
//   Property 'effect' is missing in type '{ hit: true; damage: number; }' but required in type 'Kick'.

interfaceとtypeの違い

1.interfaceではオブジェクトとクラスの型だけ定義できるが、typeでは他の型も参照できる

2.interfaceは拡張ができるが、typeはできない(スコープ内で重複できない)

interface User {
  name: string;
}

interface User {
  level: number;
}

const user: User = {
  name: "apple",
  level: 0
};

------------------------------------------------------

type User = {
  name: string;
} //Duplicate identifier 'User'

type User = {
  level: number;
} //Duplicate identifier 'User'

3.typeのみ三項演算子が使える

type User<T extends boolean> = T extends true ? number : string

const truthyValue: User<true> = 156;
const falsyValue: User<false> = '愛本輪怐';

4.typeは数も同じでなければならない(タプル)

interface A {
    0: number;
    1: string;
    2: number;
}

type B = [number, string, number];

// ok
const a: A = [0, '1', 2, 3];

const b: B = [0, '1', 2, 3]
// Type '[number, string, number, number]' is not assignable to type 'B'.
//   Types of property 'length' are incompatible.
//     Type '4' is not assignable to type '3'.

参考

https://zenn.dev/luvmini511/articles/6c6f69481c2d17

https://nju33.com/notes/typescript/articles/Interface と Type の比較#三項演算子https://qiita.com/tkrkt/items/d01b96363e58a7df830e

Mapped Types

指定した型を変換して新しい型を生成する機能

解説はこちら

使用例

ネストされた場合

リテラル型とプリミティブ型

プリミティブ型はnumber, string, null, undefinedなどのこと。

リテラル型とはプリミティブ型の特定の値だけを許容する型

const impossible: false = false;
const three: 3 = 3;
const radetzky: 'Radetzky' = 'Radetzky';

型アサーション(as)

型定義の上書き機能。型アサーションを使えば、任意のタイミングで型を上書きできちゃうため型安全性が全く保証されないので注意

type Foo = {
    bar: number;
    bas: string;
}

const foo = {} as Foo;
foo.bar = 123;
foo.bas = 'hello';

unknownとanyの違い

unknown型に代入したオブジェクトのプロパティ、メソッドは型ガードや型アサーションを経由しないと使用(実行)できない。

const unknown1: unknown = 0.8;
const unknown2: unknown = 'Comment allez-vous';
const unknown3: unknown = {
  x: 0,
  y: 1,
  name: 'origin'
};

console.log(unknown1.toFixed());
// Object is of type 'unknown'.
console.log(unknown2.length);
// Object is of type 'unknown'.
console.log(unknown3.name);
// Object is of type 'unknown'.

anyと違い、型ガードはしっかりされる

function toString(n: unknown): string {
  switch (typeof n) {
    case 'object':
      if (n === null) {
        return  n.substr(1);
        // Object is possibly 'null'.
      }
      return  n.substr(1);
      // Property 'substr' does not exist on type 'object'
    case 'string':
      return  n.substr(1);
    default:
      return  n.substr(1);
     // Object is of type 'unknown'.
  }
}

Partial

すべてのプロパティにOptional(任意)であることを意味する?を適用します。

interface User {
  name?: string,
  height?: string,
  age?: number,
}

function findUsers(
  name?: string,
  height?: string,
  age?: number,
): void {
  console.log(age);
}
// OKだけど引数の分だけundefined入れるのはだるい・・・
findUsers(undefined, undefined, 22);
interface User {
  name?: string,
  height?: string,
  age?: number,
}

type FindUsersArgs = Partial<User>;

function findUsers({ name, height, age }: FindUsersArgs): 
 void {
  console.log(age);
}

// 引数1つでOK!
findUsers({ age : 22 });

Required

すべてのプロパティからOptionalであることを意味する?を取り除く

interface User {
  name?: string,
  height?: string,
  age?: number,
}

type FindUsersArgs = Required<User>;

function findUsers({ name, height, age }: FindUsersArgs): 
 void {
  console.log(age);
}

findUsers({ age : 22 });
// Argument of type '{ age: number; }' is not assignable to parameter of type 'Required<User>'.Type '{ age: number; }' is missing the following properties from type 'Required<User>': name, height

Record

以下の書式を持つ組み込み型で、Kに指定したキーに対して、型Tを設定してくれるものです。

// Record<K extends string | number | symbol, T> Kに指定された型をキーにして,それぞれに対して、型Tを設定する。
type User = {
  address: string;
  name: String;
};

const Users:Record<number , User> = {
  1 : {
    address: "Shinjuku",
    name: "user1"
  },
  2 : {
    address: "Shibuya",
    name: "user2"
  },
  'idol':{
    address: "Nakano",
    name: "user3"
  },
// Type '{ 1: { address: string; name: string; }; 2: { address: string; name: string; }; idol: { address: string; name: string; }; }' is not assignable to type 'Record<number, User>'.Object literal may only specify known properties, and ''idol'' does not exist in type 'Record<number, User>'.
};

Pick

既に存在するT型の中からKで選択した一部のプロパティのみを含んだ新たな型を構築します。

interface Todo {
  title: string
  description: string
  completed: boolean
}
type TodoPreview = Pick<Todo, 'title' | 'completed'>

const preview: TodoPreview = {
  title: '部屋の掃除',
  completed: false,
}

console.log(preview)

Omit

Omitは既に存在するT型の中からKで選択した一部のプロパティを除いた新たな型を構築します。

interface Todo {
  title: string
  description: string
  completed: boolean
}
type TodoPreview = Omit<Todo, 'description'>

const preview: TodoPreview = {
  title: '部屋の掃除',
  completed: false,
}
console.log(preview) //=> { title: '部屋の掃除', completed: false }

// export interface MaintenanceConfirmData
//   extends Omit<MaintenanceRequestData, 'old_inputs'> {
//   inputs: MaintenanceRequestForm;
// }

Exclude

ユニオン型TからUを取り除きます。

type Grade = 'A' | 'B' | 'C' | 'D' | 'E';
// A~DがOK
type PassGrade = Exclude<Grade, 'E'>;

Extract

Excludeと逆です。ユニオン型TからUを抽出します。

type Grade = 'A' | 'B' | 'C' | 'D' | 'E';
// EのみOK
type FailGrade = Extract<Grade, 'E'>;

タプル

複数の値を保持することのできる型です。 [] 記号を使うところも配列によく似ていますが、それぞれの位置の要素の型を明示しておくことができます。

let vote: [string,number]
vote = ['red', 100];// OK
vote = ['green', 200];// OK
vote = ['yellow', 300];// OK
vote = ['AAA', 'BBB'];// Error

参考: https://maku.blog/p/6uzqf4q/

ユニオン型 (Union Types)

こちら

ReturnType

関数の返り値を型に変換する

const foo = ()=> {
  return {
    foo: 1,
    fooo: 2,
    foooo: 3
  }
}

type Foo = ReturnType<typeof foo>

/* type Foo = {
	foo: 1,
	fooo: 2,
	foooo: 3
}
*/
6
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
6
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?